一、通讯录

iOS中的通讯录是存储在数据库中的,由于iOS的权限设计,开发人员是不允许直接访问通讯录数据库的,实现通讯录操作需要使用到AddressBook.framework框架。

AddressBook.framework框架:
  • 可以从底层去操作通讯录的所有信息,做到精确控制
  • 是基于C语言编写的,无法使用ARC管理内存,需要开发者手动管理内存
  • 需要自构UI界面

iOS还提供了另外一个框架来供开发者操作通讯录,那就是AddressBookUI.framework

AddressBookUI.framework框架:
  • 该框架封装AddressBook.framework,向外提供现成视图控制器使用
  • 可以使用ARC管理内存
  • 高度封装化,界面固定,可定制性差

这两个框架各有各的优点,各有各的缺点,具体采用哪一种去操作通讯录看具体需求决定。

二、AddressBook

AddressBook.framework框架是基于C语言的,缺少面向对象的思想,所以我们可以把里面一些结构体理解为一个“类”

首先我们来了解几个核心结构体:
  1. ABAddressBookRef
    通讯录对象,全局管理通讯录操作,比如修改保存等
  2. ABRecordRef
    通用的记录对象,可以是一条联系人信息,也可以是一个群组,通过具体类型进行区分,每条记录都有一个唯一ID标识
  3. ABPersonRef
    联系人信息,不常用,可以用类型为kABPersonTypeABRecordRef代替。
  4. ABGroupRef
    群组信息,不常用,可以用类型为kABGroupTypeABRecordRef代替。
常使用到关于记录Record的C语言函数:
/* 获取一条记录对象的唯一标识ID */
ABRecordID ABRecordGetRecordID(ABRecordRef record);
/* 创建一条记录对象,类型为kABPersonType,表示一条联系人信息 */
ABRecordRef ABPersonCreate(void);
/* 创建一条记录对象,类型为kABGroupType,表示一条群组信息 */
ABRecordRef ABGroupCreate(void);
/* 获取指定属性的值 */
CFTypeRef ABRecordCopyValue(ABRecordRef record, ABPropertyID property);
/* 设置纪录的属性值,返回设置是否成功 */
bool ABRecordSetValue(
ABRecordRef record, /* 记录 */
ABPropertyID property, /* 属性 */
CFTypeRef value, /* 值,可以是单值,也可以是多重值 */
CFErrorRef* error /* 错误信息 */
);
/* 向多重值添加单值 */
bool ABMultiValueAddValueAndLabel(
ABMutableMultiValueRef multiValue, /* 多重值 */
CFTypeRef value, /* 单值 */
CFStringRef label, /* 单值对应的属性名 */
ABMultiValueIdentifier *outIdentifier /* 多重值的标示 */
);
/* 从多重值中取出指定索引的单值 */
CFTypeRef ABMultiValueCopyValueAtIndex(
ABMultiValueRef multiValue,
CFIndex index
);
/* 删除指定的属性值 */
bool ABRecordRemoveValue(
ABRecordRef record, /* 记录 */
ABPropertyID property, /* 属性 */
CFErrorRef* error /* 错误信息 */
);
常使用到的通讯录操作的函数
/* 创建通讯录对象 */
ABAddressBookRef ABAddressBookCreate(void);
/* 操作通讯录用户授权,注意无论成功与否回调都会调用 */
void ABAddressBookRequestAccessWithCompletion(
ABAddressBookRef addressBook, /* 通讯录 */
ABAddressBookRequestAccessCompletionHandler completion /* 回调 */
);
/* 获取通讯录所有的记录 */
CFArrayRef ABAddressBookCopyArrayOfAllPeople(ABAddressBookRef addressBook);
/* 添加记录进通讯录 */
bool ABAddressBookAddRecord(
ABAddressBookRef addressBook, /* 通讯录 */
ABRecordRef record, /* 记录 */
CFErrorRef* error /* 错误信息 */
);
/* 从通讯录删除记录 */
bool ABAddressBookRemoveRecord(
ABAddressBookRef addressBook,/* 通讯录 */
ABRecordRef record, /* 记录 */
CFErrorRef* error/* 错误信息 */
);
/* 从通讯录中获取一个记录,根据记录ID */
ABRecordRef ABAddressBookGetPersonWithRecordID(
ABAddressBookRef addressBook, /* 通讯录 */
ABRecordID recordID /* 记录ID */
);
/* 保持通讯录,修改了通讯录需要保存提交修改 */
bool ABAddressBookSave(
ABAddressBookRef addressBook, /* 通讯录 */
CFErrorRef* error /* 错误信息 */
);
通讯录使用步骤:
  1. 创建通讯录对象ABAddressBookRef
  2. 请求用户授权操作通讯录ABAddressBookRequestAccessWithCompletion
  3. 查询所有通讯录的记录ABAddressBookCopyArrayOfAllPeople
  4. 添加记录,删除记录,修改记录
  5. 修改通讯录后,记住要通讯录保存ABAddressBookSave
下面是实际代码:
1. 创建通讯录并请求授权
/* 请求访问通讯录并获取通讯录所有记录 */
- (void)requestAddressBook{
//创建通讯录对象
self.addressBook = ABAddressBookCreate(); //请求访问用户通讯录,注意无论成功与否block都会调用
ABAddressBookRequestAccessWithCompletion(self.addressBook, ^(bool granted, CFErrorRef error) {
if (!granted) {
NSLog(@"未获得通讯录访问权限!");
}
//获取所有通讯录记录
[self initAllPerson];
//刷新表格
[self.tableView reloadData];
});
} /* 取得所有通讯录记录 */
- (void)initAllPerson{
//取得通讯录访问授权
ABAuthorizationStatus authorization = ABAddressBookGetAuthorizationStatus();
//如果未获得授权
if (authorization != kABAuthorizationStatusAuthorized) {
NSLog(@"尚未获得通讯录访问授权!");
return ;
}
//取得通讯录中所有人员记录
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(self.addressBook);
self.allPerson = (__bridge NSMutableArray *)allPeople;
//释放资源
CFRelease(allPeople);
}
2. 添加联系人

/**
* 添加一条记录
*
* @param firstName 名
* @param lastName 姓
* @param iPhoneName iPhone手机号
*/
- (void)addPersonWithFirstName:(NSString *)firstName
lastName:(NSString *)lastName
workNumber:(NSString *)workNumber
{
//创建一条记录
ABRecordRef recordRef = ABPersonCreate();
//添加名
ABRecordSetValue(recordRef,kABPersonFirstNameProperty,(__bridge CFTypeRef)(firstName),NULL);
//添加姓
ABRecordSetValue(recordRef,kABPersonLastNameProperty,(__bridge CFTypeRef)(lastName),NULL);
//创建一个多值属性,因为手机号可以有多个
ABMutableMultiValueRef multiValueRef = ABMultiValueCreateMutable(kABStringPropertyType);
//向多值属性中添加工作电话
ABMultiValueAddValueAndLabel(multiValueRef,(__bridge CFStringRef)(workNumber),kABWorkLabel,NULL);
//添加属性到指定记录,这里添加的是多值属性
ABRecordSetValue(recordRef, kABPersonPhoneProperty, multiValueRef, NULL);
//添加记录到通讯录
ABAddressBookAddRecord(self.addressBook, recordRef, NULL);
//保存通讯录,提交更改
ABAddressBookSave(self.addressBook, NULL);
//释放资源
CFRelease(recordRef);
CFRelease(multiValueRef);
}
3. 删除联系人
/* 删除指定的记录 */
- (void)removePersonWithRecord:(ABRecordRef)recordRef{
ABAddressBookRemoveRecord(self.addressBook, recordRef, NULL);//删除
ABAddressBookSave(self.addressBook, NULL);//删除之后提交更改
}
/* 根据姓名删除记录 */
- (void)removePersonWithName:(NSString *)personName{
CFStringRef personNameRef = (__bridge CFStringRef)(personName);
//根据人员姓名查找
CFArrayRef recordsRef = ABAddressBookCopyPeopleWithName(self.addressBook, personNameRef);
CFIndex count = CFArrayGetCount(recordsRef);//取得记录数
for (CFIndex i=0; i<count; ++i) {
ABRecordRef recordRef = CFArrayGetValueAtIndex(recordsRef, i);//取得指定的记录
ABAddressBookRemoveRecord(self.addressBook, recordRef, NULL);//删除
}
//删除之后提交更改
ABAddressBookSave(self.addressBook, NULL);
CFRelease(recordsRef);
}
4. 修改联系人
/**
* 根据记录ID修改联系人信息
*
* @param recordID 记录唯一ID
* @param firstName 姓
* @param lastName 名
* @param homeNumber 工作电话
*/
- (void)modifyPersonWithRecordID:(ABRecordID)recordID
firstName:(NSString *)firstName
lastName:(NSString *)lastName
workNumber:(NSString *)workNumber
{
//根据记录ID获取一条记录
ABRecordRef recordRef = ABAddressBookGetPersonWithRecordID(self.addressBook, recordID);
//添加名
ABRecordSetValue(recordRef,kABPersonFirstNameProperty,(__bridge CFTypeRef)(firstName),NULL);
//添加姓
ABRecordSetValue(recordRef,kABPersonLastNameProperty,(__bridge CFTypeRef)(lastName),NULL);
//创建一个多值属性,因为手机号可以有多个
ABMutableMultiValueRef multiValueRef = ABMultiValueCreateMutable(kABStringPropertyType);
//向多值属性中添加工作电话
ABMultiValueAddValueAndLabel(multiValueRef,(__bridge CFStringRef)(workNumber),kABWorkLabel,NULL);
//添加属性到指定记录,这里添加的是多值属性
ABRecordSetValue(recordRef, kABPersonPhoneProperty, multiValueRef, NULL);
//保存记录,提交更改
ABAddressBookSave(self.addressBook, NULL);
//释放资源
CFRelease(multiValueRef);
}
5. UITableView显示
#pragma mark - TableView代理和数据源
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
{
if (!self.allPerson) {
return 0;
}
return self.allPerson.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *key = @"cellIdentify";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:key];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1
reuseIdentifier:key];
}
//取得一条人员记录
ABRecordRef recordRef = (__bridge ABRecordRef)self.allPerson[indexPath.row];
//取得记录中得信息,注意这里进行了强转,不用自己释放资源
NSString *firstName = (__bridge NSString *)ABRecordCopyValue(recordRef, kABPersonFirstNameProperty);
NSString *lastName = (__bridge NSString *)ABRecordCopyValue(recordRef, kABPersonLastNameProperty);
//获取手机号,注意手机号是ABMultiValueRef类,有可能有多条
ABMultiValueRef phoneNumbersRef = ABRecordCopyValue(recordRef, kABPersonPhoneProperty);
long count = ABMultiValueGetCount(phoneNumbersRef);
for(int i = 0;i < count;++i){
NSString *phoneLabel = (__bridge NSString *)(ABMultiValueCopyLabelAtIndex(phoneNumbersRef, i));
NSString *phoneNumber = (__bridge NSString *)(ABMultiValueCopyValueAtIndex(phoneNumbersRef, i));
NSLog(@"%@:%@",phoneLabel,phoneNumber);
}
cell.textLabel.text = [NSString stringWithFormat:@"%@ %@",firstName,lastName];
if (count > 0) {
cell.detailTextLabel.text = (__bridge NSString *)(ABMultiValueCopyValueAtIndex(phoneNumbersRef, 0));
}
//使用cell的tag存储记录ID
cell.tag = ABRecordGetRecordID(recordRef);
//记录最后一个记录的ID
if (indexPath.row == self.allPerson.count - 1) {
self.lastID = ABRecordGetRecordID(recordRef);
}
return cell;
}
6. UI点击以及视图控制器初始化和销毁
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.delegate = self;
self.tableView.dataSource = self;
//请求访问通讯录并获取通讯录所有记录
[self requestAddressBook];
}
//由于在整个视图控制器周期内addressBook都驻留在内存中,所以当控制器视图销毁时销毁该对象
- (void)dealloc{
if (self.addressBook != NULL) {
CFRelease(self.addressBook);
}
}
#pragma mark - UI点击
- (IBAction)addPerson:(id)sender {
//添加联系人
[self addPersonWithFirstName:@"liu"
lastName:@"ting"
workNumber:@"13412321332"];
//获取所有通讯录记录
[self initAllPerson];
//刷新表格
[self.tableView reloadData];
}
- (IBAction)removePerson:(id)sender {
//删除联系人
[self removePersonWithName:@"liu ting"];
//获取所有通讯录记录
[self initAllPerson];
//刷新表格
[self.tableView reloadData];
}
- (IBAction)changePerson:(id)sender {
[self modifyPersonWithRecordID:self.lastID
firstName:@"XXXX"
lastName:@"YYY"
workNumber:@"1111111111"];
//获取所有通讯录记录
[self initAllPerson];
//刷新表格
[self.tableView reloadData];
}

三、AddressBookUI

AddressBookUI这个框架就提供了现成的控制器视图供开发者使用,高度封装化。

下面是这个框架中提供的控制器视图:
  1. ABPersonViewController
    用于查看联系人信息(可设置编辑)。
    需要设置displayedPerson属性来设置要显示或编辑的联系人。
  2. ABNewPersonViewController
    用于新增联系人信息。
  3. ABUnknownPersonViewController
    用于显示一个未知联系人(尚未保存的联系人)信息。
    需要设置displayedPerson属性来设置要显示的未知联系人。
  4. ABPeoplePickerNavigationController
    用于选择联系人。

前面三个控制器视图均继承于UIViewController,在使用过程中必须使用一个UINavigationController进行包装,否则只能看到视图内容无法进行操作,并且必须处理控制器的关闭操作,可以通过代理方法获得新增、修改的联系人。
最后一个控制器视图继承于UINavigationController,视图自身的“组”、“取消”按钮操作不需要开发者来完成,例如开发者不用在点击取消时关闭当前控制器视图,它自身已经实现了关闭方法。

下面是这四个控制器的代理方法:
#pragma mark - ABPersonViewController代理方法
//选择一个人员属性后触发,返回值YES表示触发默认行为操作,否则执行代理中自定义的操作
- (BOOL)personViewController:(ABPersonViewController *)personViewController
shouldPerformDefaultActionForPerson:(ABRecordRef)person
property:(ABPropertyID)property
identifier:(ABMultiValueIdentifier)identifier;
#pragma mark - ABNewPersonViewController代理方法
/*
完成新增(点击取消和完成按钮时调用),注意这里不用做实际的通讯录增加工作,
此代理方法调用时已经完成新增,当保存成功的时候参数中得person会返回保存的记录,如果点击取消person为NULL
*/
- (void)newPersonViewController:(ABNewPersonViewController *)newPersonView
didCompleteWithNewPerson:(ABRecordRef)person;
#pragma mark - ABUnknownPersonViewController代理方法
//保存未知联系人时触发
- (void)unknownPersonViewController:(ABUnknownPersonViewController *)unknownCardViewController
didResolveToPerson:(ABRecordRef)person;
#pragma mark - ABPeoplePickerNavigationController代理方法
//选择一个联系人后调用,注意这个代理方法实现后选择属性的方法将不会再调用
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
didSelectPerson:(ABRecordRef)person;
//选择属性之后调用,注意如果上面的代理方法实现后此方法不会被调用
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
didSelectPerson:(ABRecordRef)person
property:(ABPropertyID)property
identifier:(ABMultiValueIdentifier)identifier;
//点击取消按钮调用
- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker;
下面是具体代码示例【我包装了一个全局导航控制器】:
#import "addressBookUIViewController.h"
#import <AddressBookUI/AddressBookUI.h> @interface addressBookUIViewController () <ABNewPersonViewControllerDelegate,
ABUnknownPersonViewControllerDelegate,
ABPeoplePickerNavigationControllerDelegate,
ABPersonViewControllerDelegate> @end @implementation addressBookUIViewController - (void)viewDidLoad {
[super viewDidLoad];
} #pragma mark - UI事件
//点击添加联系人
- (IBAction)addPersonClick:(UIButton *)sender {
//创建添加联系人视图控制器
ABNewPersonViewController *newPersonController =
[[ABNewPersonViewController alloc] init];
//设置代理
newPersonController.newPersonViewDelegate = self;
//注意必须有一层导航控制器才能使用,否则不会出现取消和完成按钮,无法进行保存等操作
[self.navigationController pushViewController:newPersonController animated:YES];
}
//点击未知联系人
- (IBAction)unknownPersonClick:(UIButton *)sender {
//创建未知联系人视图控制器
ABUnknownPersonViewController *unknownPersonController =
[[ABUnknownPersonViewController alloc] init];
//设置未知人员
ABRecordRef recordRef=ABPersonCreate();
ABRecordSetValue(recordRef, kABPersonFirstNameProperty, @"Kenshin", NULL);
ABRecordSetValue(recordRef, kABPersonLastNameProperty, @"Cui", NULL);
ABMultiValueRef multiValueRef = ABMultiValueCreateMutable(kABStringPropertyType);
ABMultiValueAddValueAndLabel(multiValueRef, @"18500138888", kABHomeLabel, NULL);
ABRecordSetValue(recordRef, kABPersonPhoneProperty, multiValueRef, NULL);
unknownPersonController.displayedPerson = recordRef;
//设置代理
unknownPersonController.unknownPersonViewDelegate = self;
//设置其他属性
unknownPersonController.allowsActions = YES;//显示标准操作按钮
unknownPersonController.allowsAddingToAddressBook = YES;//是否允许将联系人添加到地址簿
//释放资源
CFRelease(multiValueRef);
CFRelease(recordRef); [self.navigationController pushViewController:unknownPersonController animated:YES];
}
//点击显示联系人
- (IBAction)showPersonClick:(UIButton *)sender {
//创建显示联系人视图控制器
ABPersonViewController *personController = [[ABPersonViewController alloc] init];
//设置联系人,取得id为1的联系人记录
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
ABRecordRef recordRef = ABAddressBookGetPersonWithRecordID(addressBook, 1);
personController.displayedPerson = recordRef;
//设置代理
personController.personViewDelegate = self;
//设置其他属性
personController.allowsActions = YES;//是否显示发送信息、共享联系人等按钮
personController.allowsEditing = YES;//允许编辑 [self.navigationController pushViewController:personController animated:YES];
}
//点击选择联系人
- (IBAction)selectPersonClick:(UIButton *)sender {
//创建选择联系人导航视图控制器
ABPeoplePickerNavigationController *peoplePickerController =
[[ABPeoplePickerNavigationController alloc] init];
//设置代理
peoplePickerController.peoplePickerDelegate = self;
//以模态弹出
[self presentViewController:peoplePickerController animated:YES completion:nil];
} #pragma mark - ABNewPersonViewController代理方法
/*
完成新增(点击取消和完成按钮时调用),注意这里不用做实际的通讯录增加工作,
此代理方法调用时已经完成新增,当保存成功的时候参数中得person会返回保存的记录,
如果点击取消person为NULL
*/
- (void)newPersonViewController:(ABNewPersonViewController *)newPersonView
didCompleteWithNewPerson:(ABRecordRef)person
{
//如果有联系人信息
if (person) {
NSLog(@"%@ 信息保存成功.",(__bridge NSString *)(ABRecordCopyCompositeName(person)));
}else{
NSLog(@"点击了取消.");
}
//返回主视图窗口
[self.navigationController popToRootViewControllerAnimated:YES]; }
#pragma mark - ABUnknownPersonViewController代理方法
//保存未知联系人时触发
- (void)unknownPersonViewController:(ABUnknownPersonViewController *)unknownCardViewController
didResolveToPerson:(ABRecordRef)person
{
if (person) {
NSLog(@"%@ 信息保存成功!",(__bridge NSString *)(ABRecordCopyCompositeName(person)));
}
//返回主视图窗口
[self.navigationController popToRootViewControllerAnimated:YES];
} #pragma mark - ABPersonViewController代理方法
//选择一个人员属性后触发,返回值YES表示触发默认行为操作,否则执行代理中自定义的操作
- (BOOL)personViewController:(ABPersonViewController *)personViewController
shouldPerformDefaultActionForPerson:(ABRecordRef)person
property:(ABPropertyID)property
identifier:(ABMultiValueIdentifier)identifier
{
if (person) {
NSLog(@"选择了属性:%d",property);
NSLog(@"值为:%@", (__bridge NSString *)ABRecordCopyValue(person, property));
}
return NO;
}
#pragma mark - ABPeoplePickerNavigationController代理方法
//选择一个联系人后调用,注意这个代理方法实现后选择属性的方法将不会再调用
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
didSelectPerson:(ABRecordRef)person
{
if (person) {
NSLog(@"选择了%@.",(__bridge NSString *)(ABRecordCopyCompositeName(person)));
}
}
//点击取消按钮后调用
- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker{
NSLog(@"取消选择.");
}
@end

iOS学习笔记29-系统服务(二)通讯录的更多相关文章

  1. iOS学习笔记20-地图(二)MapKit框架

    一.地图开发介绍 从iOS6.0开始地图数据不再由谷歌驱动,而是改用自家地图,当然在国内它的数据是由高德地图提供的. 在iOS中进行地图开发主要有三种方式: 利用MapKit框架进行地图开发,利用这种 ...

  2. iOS学习笔记13-网络(二)NSURLSession

    在2013年WWDC上苹果揭开了NSURLSession的面纱,将它作为NSURLConnection的继任者.现在使用最广泛的第三方网络框架:AFNetworking.SDWebImage等等都使用 ...

  3. iOS学习笔记(十二)——iOS国际化

    开发的移动应用更希望获取更多用户,走向世界,这就需要应用国际化,国际化其实就是多语言.这篇文章介绍Xcode4.5以后的国际化,包括应用名国际化和应用内容国际化.如果是Xcode4.5之前版本请参考. ...

  4. 【转】IOS学习笔记29—提示框第三方库之MBProgressHUD

    原文网址:http://blog.csdn.net/ryantang03/article/details/7877120 MBProgressHUD是一个开源项目,实现了很多种样式的提示框,使用上简单 ...

  5. IOS学习笔记48--一些常见的IOS知识点+面试题

      IOS学习笔记48--一些常见的IOS知识点+面试题   1.堆和栈什么区别? 答:管理方式:对于栈来讲,是由编译器自动管理,无需我们手工控制:对于堆来说,释放工作由程序员控制,容易产生memor ...

  6. React Native 学习笔记--进阶(二)--动画

    React Native 进阶(二)–动画 动画 流畅.有意义的动画对于移动应用用户体验来说是非常必要的.我们可以联合使用两个互补的系统:用于全局的布局动画LayoutAnimation,和用于创建更 ...

  7. iOS学习笔记-精华整理

    iOS学习笔记总结整理 一.内存管理情况 1- autorelease,当用户的代码在持续运行时,自动释放池是不会被销毁的,这段时间内用户可以安全地使用自动释放的对象.当用户的代码运行告一段 落,开始 ...

  8. iOS学习笔记总结整理

    来源:http://mobile.51cto.com/iphone-386851_all.htm 学习IOS开发这对于一个初学者来说,是一件非常挠头的事情.其实学习IOS开发无外乎平时的积累与总结.下 ...

  9. IOS学习笔记(四)之UITextField和UITextView控件学习

    IOS学习笔记(四)之UITextField和UITextView控件学习(博客地址:http://blog.csdn.net/developer_jiangqq) Author:hmjiangqq ...

  10. IOS学习笔记06---C语言函数

    IOS学习笔记06---C语言函数 --------------------------------------------  qq交流群:创梦技术交流群:251572072              ...

随机推荐

  1. javaSe-反射1

    package com.java.chap07.sec01; public class Student { private String name; private Integer age; //创建 ...

  2. 51nod 1276 岛屿的数量

    题目来源: Codility 基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题 有N个岛连在一起形成了一个大的岛屿,如果海平面上升超过某些岛的高度时,则这个岛会被淹没 ...

  3. windows 密钥

    server 2016数据中心CB7KF-BWN84-R7R2Y-793K2-8XDDG

  4. 如何给SAP Cloud Connector Region列表中添加新的Region

    SAP help里提供了CloudFoundry和Neo环境下可用的Region和API endpoint: 当我们期望用SAP Cloud Connector连接某个SAP云平台Region时,一般 ...

  5. js 获取当前年月日时分秒星期

    $("#aa").click(function () { var date = new Date(); this.year = date.getFullYear(); this.m ...

  6. Java中 Character方法练习:字符串中英文字母个数 5435abc54abc3AHJ5 正则:matches("[a-zA-Z0-9]{1}")

    package com.swift; public class String_Letter_Number_Test { public static void main(String[] args) { ...

  7. ubuntu 16.04 +anaconda3.6 +Nvidia DRIVER 390.77 +CUDA9.0 +cudnn7.0.4+tensorflow1.5.0+neural-style

    这是我第一个人工智能实验.虽然原理不是很懂,但是觉得深度学习真的很有趣.教程如下. Table of Contents 配置 时间轴 前期准备工作 anaconda3 安装 bug 1:conda:未 ...

  8. Spring源码剖析依赖注入实现

    Spring源码剖析——依赖注入实现原理 2016年08月06日 09:35:00 阅读数:31760 标签: spring源码bean依赖注入 更多 个人分类: Java   版权声明:本文为博主原 ...

  9. Linux - mkdir -p a/b/c

    mkdir -p a/b/c -p  会循环创建

  10. 常用的windows小工具指令和如何打开自定义的程序

    windows可以通过 开始->运行->输入程序名 或 windows键+R键 两种方式来启动windows中自带的程序或手动安装的程序.下面介绍一些常用的windows工具的指令和如何打 ...