隨着apple對用戶隱私的愈來愈重視,IOS系統的權限設置也更加嚴格,在獲取系統通信錄以前,咱們必須得到用戶的受權。權限申請代碼示例以下:數組
?app
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
//這個變量用於記錄受權是否成功,即用戶是否容許咱們訪問通信錄
int
__block tip=0;
//聲明一個通信簿的引用
ABAddressBookRef addBook =nil;
//由於在IOS6.0以後和以前的權限申請方式有所差異,這裏作個判斷
if
([[UIDevice currentDevice].systemVersion floatValue]>=6.0) {
//建立通信簿的引用
addBook=ABAddressBookCreateWithOptions(NULL, NULL);
//建立一個出事信號量爲0的信號
dispatch_semaphore_t sema=dispatch_semaphore_create(0);
//申請訪問權限
ABAddressBookRequestAccessWithCompletion(addBook, ^(
bool
greanted, CFErrorRef error) {
//greanted爲YES是表示用戶容許,不然爲不容許
if
(!greanted) {
tip=1;
}
//發送一次信號
dispatch_semaphore_signal(sema);
});
//等待信號觸發
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
}
else
{
//IOS6以前
addBook =ABAddressBookCreate();
}
if
(tip) {
//作一個友好的提示
UIAlertView * alart = [[UIAlertView alloc]initWithTitle:@
"舒適提示"
message:@
"請您設置容許APP訪問您的通信錄\nSettings>General>Privacy"
delegate:self cancelButtonTitle:@
"肯定"
otherButtonTitles:nil, nil];
[alart show];
return
;
}
|
幾點注意:一、dispatch_semaphore_t三個相關的操做爲iphone
dispatch_semaphore_create 建立一個信號
dispatch_semaphore_signal 發送一個信號
dispatch_semaphore_wait 等待信號觸發 spa
dispatch_semaphore_create()建立一個信號,後面能夠跟一個參 數,表示信號量,當信號量正值時,dispatch_semaphore_wait後面的代碼會被執行,不然程序將會一直等待在 dispatch_semaphore_wait。 dispatch_semaphore_signal的做用是發送一個信號,會使信號量加1,相對 的,dispatch_semaphore_wait執行後會使信號量減1.線程
二、由於是否被受權是在ABAddressBookRequestAccessWithCompletion的block回調中獲取的,因此咱們須要在外面作一個線程等待。code
?orm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
//獲取全部聯繫人的數組
CFArrayRef allLinkPeople = ABAddressBookCopyArrayOfAllPeople(addBook);
//獲取聯繫人總數
CFIndex number = ABAddressBookGetPersonCount(addBook);
//進行遍歷
for
(NSInteger i=0; i<number; i++) {
//獲取聯繫人對象的引用
ABRecordRef people = CFArrayGetValueAtIndex(allLinkPeople, i);
//獲取當前聯繫人名字
NSString*firstName=(__bridge NSString *)(ABRecordCopyValue(people, kABPersonFirstNameProperty));
//獲取當前聯繫人姓氏
NSString*lastName=(__bridge NSString *)(ABRecordCopyValue(people, kABPersonLastNameProperty));
//獲取當前聯繫人中間名
NSString*middleName=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonMiddleNameProperty));
//獲取當前聯繫人的名字前綴
NSString*prefix=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonPrefixProperty));
//獲取當前聯繫人的名字後綴
NSString*suffix=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonSuffixProperty));
//獲取當前聯繫人的暱稱
NSString*nickName=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonNicknameProperty));
//獲取當前聯繫人的名字拼音
NSString*firstNamePhoneic=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonFirstNamePhoneticProperty));
//獲取當前聯繫人的姓氏拼音
NSString*lastNamePhoneic=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonLastNamePhoneticProperty));
//獲取當前聯繫人的中間名拼音
NSString*middleNamePhoneic=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonMiddleNamePhoneticProperty));
//獲取當前聯繫人的公司
NSString*organization=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonOrganizationProperty));
//獲取當前聯繫人的職位
NSString*job=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonJobTitleProperty));
//獲取當前聯繫人的部門
NSString*department=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonDepartmentProperty));
//獲取當前聯繫人的生日
NSString*birthday=(__bridge NSDate*)(ABRecordCopyValue(people, kABPersonBirthdayProperty));
NSMutableArray * emailArr = [[NSMutableArray alloc]init];
//獲取當前聯繫人的郵箱 注意是數組
ABMultiValueRef emails= ABRecordCopyValue(people, kABPersonEmailProperty);
for
(NSInteger j=0; j<ABMultiValueGetCount(emails); j++) {
[emailArr addObject:(__bridge NSString *)(ABMultiValueCopyValueAtIndex(emails, j))];
}
//獲取當前聯繫人的備註
NSString*notes=(__bridge NSString*)(ABRecordCopyValue(people, kABPersonNoteProperty));
//獲取當前聯繫人的電話 數組
NSMutableArray * phoneArr = [[NSMutableArray alloc]init];
ABMultiValueRef phones= ABRecordCopyValue(people, kABPersonPhoneProperty);
for
(NSInteger j=0; j<ABMultiValueGetCount(phones); j++) {
[phonerr addObject:(__bridge NSString *)(ABMultiValueCopyValueAtIndex(phones, j))];
}
//獲取建立當前聯繫人的時間 注意是NSDate
NSDate*creatTime=(__bridge NSDate*)(ABRecordCopyValue(people, kABPersonCreationDateProperty));
//獲取最近修改當前聯繫人的時間
NSDate*alterTime=(__bridge NSDate*)(ABRecordCopyValue(people, kABPersonModificationDateProperty));
//獲取地址
ABMultiValueRef address = ABRecordCopyValue(people, kABPersonAddressProperty);
for
(
int
j=0; j<ABMultiValueGetCount(address); j++) {
//地址類型
NSString * type = (__bridge NSString *)(ABMultiValueCopyLabelAtIndex(address, j));
NSDictionary * temDic = (__bridge NSDictionary *)(ABMultiValueCopyValueAtIndex(address, j));
//地址字符串,能夠按需求格式化
NSString * adress = [NSString stringWithFormat:@
"國家:%@\n省:%@\n市:%@\n街道:%@\n郵編:%@"
,[temDic valueForKey:(NSString*)kABPersonAddressCountryKey],[temDic valueForKey:(NSString*)kABPersonAddressStateKey],[temDic valueForKey:(NSString*)kABPersonAddressCityKey],[temDic valueForKey:(NSString*)kABPersonAddressStreetKey],[temDic valueForKey:(NSString*)kABPersonAddressZIPKey]];
}
//獲取當前聯繫人頭像圖片
NSData*userImage=(__bridge NSData*)(ABPersonCopyImageData(people));
//獲取當前聯繫人記念日
NSMutableArray * dateArr = [[NSMutableArray alloc]init];
ABMultiValueRef dates= ABRecordCopyValue(people, kABPersonDateProperty);
for
(NSInteger j=0; j<ABMultiValueGetCount(dates); j++) {
//獲取記念日日期
NSDate * data =(__bridge NSDate*)(ABMultiValueCopyValueAtIndex(dates, j));
//獲取記念日名稱
NSString * str =(__bridge NSString*)(ABMultiValueCopyLabelAtIndex(dates, j));
NSDictionary * temDic = [NSDictionary dictionaryWithObject:data forKey:str];
[dateArr addObject:temDic];
}
|
一點擴展:相同的方法,能夠獲取關聯人信息,社交信息,郵箱信息,各類類型的電話信息,字段以下:對象
?圖片
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
//相關人,組織字段
const
ABPropertyID kABPersonKindProperty;
const
CFNumberRef kABPersonKindPerson;
const
CFNumberRef kABPersonKindOrganization;
// 電話相關字段
AB_EXTERN
const
ABPropertyID kABPersonPhoneProperty;
AB_EXTERN
const
CFStringRef kABPersonPhoneMobileLabel;
AB_EXTERN
const
CFStringRef kABPersonPhoneIPhoneLabel
AB_EXTERN
const
CFStringRef kABPersonPhoneMainLabel;
AB_EXTERN
const
CFStringRef kABPersonPhoneHomeFAXLabel;
AB_EXTERN
const
CFStringRef kABPersonPhoneWorkFAXLabel;
AB_EXTERN
const
CFStringRef kABPersonPhoneOtherFAXLabel
AB_EXTERN
const
CFStringRef kABPersonPhonePagerLabel;
// 即時聊天信息相關字段
AB_EXTERN
const
ABPropertyID kABPersonInstantMessageProperty;
AB_EXTERN
const
CFStringRef kABPersonInstantMessageServiceKey;
AB_EXTERN
const
CFStringRef kABPersonInstantMessageServiceYahoo;
AB_EXTERN
const
CFStringRef kABPersonInstantMessageServiceJabber;
AB_EXTERN
const
CFStringRef kABPersonInstantMessageServiceMSN;
AB_EXTERN
const
CFStringRef kABPersonInstantMessageServiceICQ;
AB_EXTERN
const
CFStringRef kABPersonInstantMessageServiceAIM;
AB_EXTERN
const
CFStringRef kABPersonInstantMessageServiceQQ
AB_EXTERN
const
CFStringRef kABPersonInstantMessageServiceGoogleTalk;
AB_EXTERN
const
CFStringRef kABPersonInstantMessageServiceSkype;
AB_EXTERN
const
CFStringRef kABPersonInstantMessageServiceFacebook;
AB_EXTERN
const
CFStringRef kABPersonInstantMessageServiceGaduGadu;
AB_EXTERN
const
CFStringRef kABPersonInstantMessageUsernameKey;
// 我的網頁相關字段
AB_EXTERN
const
ABPropertyID kABPersonURLProperty;
AB_EXTERN
const
CFStringRef kABPersonHomePageLabel;
//相關人姓名字段
AB_EXTERN
const
ABPropertyID kABPersonRelatedNamesProperty;
AB_EXTERN
const
CFStringRef kABPersonFatherLabel;
// Father
AB_EXTERN
const
CFStringRef kABPersonMotherLabel;
// Mother
AB_EXTERN
const
CFStringRef kABPersonParentLabel;
// Parent
AB_EXTERN
const
CFStringRef kABPersonBrotherLabel;
// Brother
AB_EXTERN
const
CFStringRef kABPersonSisterLabel;
// Sister
AB_EXTERN
const
CFStringRef kABPersonChildLabel;
// Child
AB_EXTERN
const
CFStringRef kABPersonFriendLabel;
// Friend
AB_EXTERN
const
CFStringRef kABPersonSpouseLabel;
// Spouse
AB_EXTERN
const
CFStringRef kABPersonPartnerLabel;
// Partner
AB_EXTERN
const
CFStringRef kABPersonAssistantLabel;
// Assistant
AB_EXTERN
const
CFStringRef kABPersonManagerLabel;
// Manager
|
看到上面讀取信息的代碼,你可能以爲一陣目炫,其實只是字段比較長,邏輯仍是很簡單的,一樣,寫的操做與之相似,建立,修改,刪除,是咱們對通信錄「寫」的經常使用操做。ip
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
//建立一個聯繫人引用
ABRecordRef person = ABPersonCreate();
NSString *firstName = @
"哈"
;
NSString *lastName = @
"哈"
;
// 電話號碼數組
NSArray *phones = [NSArray arrayWithObjects:@
"123"
,@
"456"
,nil];
// 電話號碼對應的名稱
NSArray *labels = [NSArray arrayWithObjects:@
"iphone"
,@
"home"
,nil];
//這裏的字段和上面的字段徹底相同
// 設置名字屬性
ABRecordSetValue(person, kABPersonFirstNameProperty,(__bridge CFStringRef)firstName, NULL);
// 設置姓氏屬性
ABRecordSetValue(person, kABPersonLastNameProperty, (__bridge CFStringRef)lastName, NULL);
// 設置生日屬性
ABRecordSetValue(person, kABPersonBirthdayProperty,(__bridge CFDateRef)birthday, NULL);
// 字典引用
ABMultiValueRef dic =ABMultiValueCreateMutable(kABMultiStringPropertyType);
// 添加電話號碼與其對應的名稱內容
for
(
int
i = 0; i < [phones count]; i ++) {
ABMultiValueIdentifier obj = ABMultiValueAddValueAndLabel(dic,(__bridge CFStringRef)[phones objectAtIndex:i], (__bridge CFStringRef)[labels objectAtIndex:i], &obj);
}
// 設置phone屬性
ABRecordSetValue(person, kABPersonPhoneProperty, dic, NULL);
// 將新建的聯繫人添加到通信錄中
ABAddressBookAddRecord(addBook, person, NULL);
// 保存通信錄數據
ABAddressBookSave(addBook, NULL);
|
修改聯繫人的操做就是將獲取和添加和在一塊兒,先獲取到相應的聯繫人引用,重設其屬性字段便可。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
//獲取全部聯繫人
NSArray *array = (__bridge NSArray*)ABAddressBookCopyArrayOfAllPeople(addBook);
// 遍歷全部的聯繫人
for
(id obj in array) {
ABRecordRef people = (__bridge ABRecordRef)obj;
NSString *firstName = (__bridge NSString*)ABRecordCopyValue(people, kABPersonFirstNameProperty);
NSString *lastName = (__bridge NSString*)ABRecordCopyValue(people, kABPersonLastNameProperty);
if
([firstName isEqualToString:@
"哈"
] &&[lastName isEqualToString:@
"哈"
]) {
ABAddressBookRemoveRecord(addBook, people,NULL);
}
}
// 保存修改的通信錄對象
ABAddressBookSave(addBook, NULL);
|
上面的代碼爲了演示方便,建立的所有引用都沒有釋放,勢必是形成內存泄露,在咱們用ABAddressBookCreate()建立一個引用對象時,切記不管ARC還MRC,要用CFRelease()進行釋放引用,例如上面的例子,咱們須要加上這句代碼
CFRelease(addBook);
若是你耐心的看到了這裏,我想你必定明白了我爲何不在前邊的代碼裏說明這個問題,由於在ARC項目普及的如今,這的確是重中之重。