[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] 访问和使用系统通讯录)