標籤:ios 系統通訊錄 移動開發
匯入AddressBook和AddressBookUI架構
iOS 6之前,可以通過如下方法獲得通訊錄
ABAddressBookRef addressBook = ABAddressBookCreate();
不過在iOS 6之後,這個方法被廢棄,可以使用下面的方法獲得通訊錄。
AB_EXTERN ABAddressBookRef ABAddressBookCreateWithOptions(CFDictionaryRef options, CFErrorRef* error) __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_6_0);
而且在ios6之後,每個App要訪問通訊錄都應該得到使用者的授權:
//系統定義的block
typedef void(^ABAddressBookRequestAccessCompletionHandler)(bool granted, CFErrorRef error);
//擷取授權的方法,其中第二個參數是上面定義的block
AB_EXTERN void ABAddressBookRequestAccessWithCompletion(ABAddressBookRef addressBook, ABAddressBookRequestAccessCompletionHandler completion) __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_6_0);
代碼如下:
-(void)getAddress{ //typedef CFTypeRef ABAddressBookRef; //typedef const void * CFTypeRef; //指向常量的指標 ABAddressBookRef addressBook = nil; //判斷當前系統的版本 if ([[UIDevice currentDevice].systemVersion floatValue] >= 6.0) { //如果不小於6.0,使用對應的api擷取通訊錄,注意,必須先請求使用者的同意,如果未獲得同意或者使用者未操作,此通訊錄的內容為空白 addressBook = ABAddressBookCreateWithOptions(NULL, NULL);//等待同意後向下執行//為了保證使用者同意後在進行操作,此時使用多線程的訊號量機制,建立訊號量,訊號量的資源數0表示沒有資源,調用dispatch_semaphore_wait會立即等待。若對此處不理解,請參看GCD訊號量同步相關內容。 dispatch_semaphore_t sema = dispatch_semaphore_create(0);//發出訪問通訊錄的請求 ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error){ //如果使用者同意,才會執行此block裡面的方法 //此方法發送一個訊號,增加一個資源數 dispatch_semaphore_signal(sema);}); //如果之前的block沒有執行,則sema的資源數為零,程式將被阻塞 //當使用者選擇同意,block的方法被執行, sema資源數為1; dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); dispatch_release(sema); }//如果系統是6.0之前的系統,不需要獲得同意,直接存取else{ addressBook = ABAddressBookCreate(); } //通訊錄資訊已獲得,開始取出 CFArrayRef results = ABAddressBookCopyArrayOfAllPeople(addressBook); //連絡人條目數(使用long而不使用int是為了相容64位) long peopleCount = CFArrayGetCount(results); for (int i=0; i<peopleCount; i++) { ABRecordRef record = CFArrayGetValueAtIndex(results, i); NSString *firstName,*lastName; firstName = nil; lastName= nil; CFTypeRef tmp = NULL; //firstName tmp = ABRecordCopyValue(record, kABPersonFirstNameProperty); if (tmp) { firstName = [NSString stringWithString:tmp]; CFRelease(tmp);tmp = NULL; } //lastName tmp = ABRecordCopyValue(record, kABPersonLastNameProperty); if (tmp){ lastName= [NSString stringWithString:tmp]; CFRelease(tmp); tmp = NULL; } //取得完整名字(與上面firstName、lastName無關) CFStringRef fullName=ABRecordCopyCompositeName(record); NSLog(@"%@",(NSString*)fullName); // 讀取電話,不只一個 ABMultiValueRef phones = ABRecordCopyValue(record, kABPersonPhoneProperty); long phoneCount = ABMultiValueGetCount(phones); for (int j=0; j<phoneCount; j++) { // label CFStringRef lable = ABMultiValueCopyLabelAtIndex(phones, j); // phone number CFStringRef number = ABMultiValueCopyValueAtIndex(phones, j); // localize label CFStringRef local = ABAddressBookCopyLocalizedLabel(lable); //此處可使用一個自訂的model類來儲存姓名和電話資訊。我在這裡就直接輸出了。 NSLog(@"number%@" ,(NSString *)number); if (local)CFRelease(local); if (lable) CFRelease(lable); if (number)CFRelease(number); } if (phones) CFRelease(phones); record = NULL; } if (results)CFRelease(results);results = nil;if (addressBook)CFRelease(addressBook);addressBook = NULL;}
請求訪問通訊錄,只有第一次會彈出警示框詢問使用者。可通過以下方法判斷狀態來提醒使用者
typedef CF_ENUM(CFIndex, ABAuthorizationStatus) { kABAuthorizationStatusNotDetermined = 0, kABAuthorizationStatusRestricted, kABAuthorizationStatusDenied, kABAuthorizationStatusAuthorized }; AB_EXTERN ABAuthorizationStatus ABAddressBookGetAuthorizationStatus(void) __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_6_0);
//獲得狀態,根據狀態判斷
ABAuthorizationStatus statu=ABAddressBookGetAuthorizationStatus();
[ios] ios6 ios7 訪問和使用系統通訊錄