SJABHelper.h
#import <Foundation/Foundation.h>enum { ABHelperCanNotConncetToAddressBook, /**< 串連通訊錄失敗(iOS6之後訪問通訊錄需要使用者許可) */ ABHelperExistSpecificContact, /**< 號碼已存在 */ ABHelperNotExistSpecificContact /**< 號碼不存在 */};typedef NSUInteger ABHelperCheckExistResultType;@interface SJABHelper : NSObject/** * 新增連絡人... * * @param name 連絡人姓名 * @param num 電話號碼 * @param label 電話號碼的標籤備忘 * * @return 是否添加成功 */+ (BOOL)addContactName:(NSString*)name phoneNum:(NSString*)num withLabel:(NSString*)label;/** * 查詢指定號碼是否已存在於通訊錄中 * * @param phoneNum 電話號碼 * * @return 返回查詢結果,詳見枚舉類型注釋 */+ (ABHelperCheckExistResultType)existPhone:(NSString*)phoneNum;@end
SJABHelper.m
需要引入 AddressBook framework。
#import "SJABHelper.h"#import <AddressBook/AddressBook.h>@implementation SJABHelper+ (SJABHelper*)shareControl{ static SJABHelper *instance; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ instance = [[SJABHelper alloc] init]; }); return instance;}- (id)init{ self = [super init]; if (self) { } return self;}+ (BOOL)addContactName:(NSString *)name phoneNum:(NSString *)num withLabel:(NSString *)label{ return [[SJABHelper shareControl] addContactName:name phoneNum:num withLabel:label];}- (BOOL)addContactName:(NSString*)name phoneNum:(NSString*)num withLabel:(NSString*)label{ ABRecordRef record = ABPersonCreate(); CFErrorRef error; // 使用 __bridge_retained 關鍵字將 NSString 轉換為 CFString 類型並將記憶體管理權從 ARC 移交出來 CFStringRef cf_name = (__bridge_retained CFTypeRef)name; CFStringRef cf_num = (__bridge_retained CFTypeRef)num; CFStringRef cf_label = (__bridge_retained CFTypeRef)label; ABRecordSetValue(record, kABPersonFirstNameProperty, cf_name, &error); ABMutableMultiValueRef multi = ABMultiValueCreateMutable(kABPersonPhoneProperty); ABMultiValueAddValueAndLabel(multi, cf_num, cf_label, NULL); ABRecordSetValue(record, kABPersonPhoneProperty, multi, &error); CFRelease(multi); ABAddressBookRef addressBook = nil; if ([[UIDevice currentDevice].systemVersion floatValue] >= 6.0) { addressBook = ABAddressBookCreateWithOptions(NULL, NULL); //等待同意後向下執行 dispatch_semaphore_t sema = dispatch_semaphore_create(0); ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) { dispatch_semaphore_signal(sema); }); dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); dispatch_release(sema); } else { addressBook = ABAddressBookCreate(); } BOOL success = ABAddressBookAddRecord(addressBook, record, &error); if (!success) { CFRelease(record); CFRelease(addressBook); return NO; }else{ success = ABAddressBookSave(addressBook, &error); CFRelease(record); CFRelease(addressBook); return success ? YES : NO; }}+ (ABHelperCheckExistResultType)existPhone:(NSString *)phoneNum{ return [[SJABHelper shareControl] existPhone:phoneNum];}- (ABHelperCheckExistResultType)existPhone:(NSString*)phoneNum{ ABAddressBookRef addressBook = nil; if ([[UIDevice currentDevice].systemVersion floatValue] >= 6.0) { addressBook = ABAddressBookCreateWithOptions(NULL, NULL); //等待同意後向下執行 dispatch_semaphore_t sema = dispatch_semaphore_create(0); ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) { dispatch_semaphore_signal(sema); }); dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); dispatch_release(sema); } else { addressBook = ABAddressBookCreate(); } CFArrayRef records; if (addressBook) { records = ABAddressBookCopyArrayOfAllPeople(addressBook); }else{#ifdef DEBUG NSLog(@"can not connect to address book");#endif return ABHelperCanNotConncetToAddressBook; } for (int i=0; i<CFArrayGetCount(records); i++) { ABRecordRef record = CFArrayGetValueAtIndex(records, i); CFTypeRef items = ABRecordCopyValue(record, kABPersonPhoneProperty); CFArrayRef phoneNums = ABMultiValueCopyArrayOfAllValues(items); if (phoneNums) { for (int j=0; j<CFArrayGetCount(phoneNums); j++) { CFStringRef cf_phone = CFArrayGetValueAtIndex(phoneNums, j); NSString *phone = (__bridge NSString *)cf_phone; if ([phoneNum isEqualToString:phone]) { CFRelease(phoneNums); CFRelease(items); CFRelease(records); CFRelease(addressBook); return ABHelperExistSpecificContact; } } CFRelease(phoneNums); } CFRelease(items); } CFRelease(records); CFRelease(addressBook); return ABHelperNotExistSpecificContact;}@end
需要注意的就是iOS6中新的使用者隱私保護使得調用 ABAddressBookCreate() 時會彈出alert讓使用者確認是否允許,需要加上代碼:
// 如果為iOS6以上系統,需要等待使用者確認是否允許訪問通訊錄。 if ([[UIDevice currentDevice].systemVersion floatValue] >= 6.0) { addressBook = ABAddressBookCreateWithOptions(NULL, NULL); //等待同意後向下執行 dispatch_semaphore_t sema = dispatch_semaphore_create(0); ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) { dispatch_semaphore_signal(sema); }); dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); dispatch_release(sema); }
不然addressBook在使用者確認操作前是NULL,調用會導致程式crash。