2015-05-22 15:55:13 huge9 阅读数 483

1、ABAddressBook

1、在ios6之前,访问系统通讯录是不需要征得用户同意的,访问通讯录的方法如下所示:
ABAddressBookRef ABAddressBookCreate ( void ),返回一个包含通讯录信息的ABAddressBookRef实例
在ios6(包括)ios6之后,访问系统通讯录是需要征的用户同意的,访问通讯录的方法也改变了,方法如下所示:
ABAddressBookRef ABAddressBookCreateWithOptions ( CFDictionaryRef options, CFErrorRef *error);
具体的视线可以参考我写的代码:
代码补充说明:
[按照网上所属,block里面的方法是只有在用户成功授权的情况下,才会走,不过我写了demo去测试,发现,无论用户同不同意授权,block都会调用,信号量都会加1,程序会继续向下进行]。
如果用户同意,则 CFArrayRef results =  ABAddressBookCopyArrayOfAllPeople(addressBook)方法返回的结果就是系统通讯录的copy;
如果用户不同意,CFArrayRef results =  ABAddressBookCopyArrayOfAllPeople(addressBook)返回的结果是空的。
为了安全判断,如下代码所示,我在copy通讯录信心前又加了安全判断,判断用户是否成功授权。
        dispatch_semaphore_t sema = dispatch_semaphore_create(0);
        
if ([UIDevice currentDevice].systemVersion.floatValue >= 6.0) {
            addressBook = 
ABAddressBookCreateWithOptions(NULLNULL);
            
//发出访问通讯录的请求
            
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error){
                
//信号量加1
                
dispatch_semaphore_signal(sema);
            });
            
//如果信号量仍未0,则等待,知道得到用户的授权
            
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
        }
else{
            
//ios6之前的方法
            addressBook = 
ABAddressBookCreate();
        }
        #warnging
        
if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized) {
            
CFArrayRef results =  ABAddressBookCopyArrayOfAllPeople(addressBook);
            
long peopleCount = CFArrayGetCount(results);
            
if (peopleCount >= 0) {
                [
self presentABPeopleNav];
            }
        }
    }
   2、ABPeoplePickerNavigationController


ABPeoplePickerNavigationController的使用就和UIImagePickerViewController的使用是一样的。
在ios8之前需要需要用户授权,授权成功之后才可以访问
但是在ios8之后,不会提示用户是否授权,可以直接访问
苹果官方文档解释如下所示:

In iOS 8 and later bringing up a people-picker navigtion controller does not require the app to have access to a user’s contacts, and the user will not be prompted to grant access. If the app does not itself have access to the user’s contacts, a temporary copy of the contact selected by the user will be returned to the app.

ABPeoplePickerNavigationController也有对应的代理方法,可以实现用户对通讯录的操作。要注意的时,ios7和ios8使用的代理方法是有区别的。ios8下会有意想不到的bug,到目前为止遇到了两个:
第一个bug:进入到信息人详情页后,会突然dismiss
解决办法是:
在实例化ABPeoplePickerNavigationController时,加上下面的代码
if ([UIDevice currentDevice].systemVersion.floatValue >= 8.0){
        
//点击联系人跳转到联系人详情界面
        peoplePicker.
predicateForSelectionOfPerson = [NSPredicate predicateWithValue:FALSE];//防止进入详情页的时候突然dismissios8bug
    }

第二个bug:点击联系电话时,跳转到了拨打电话的界面
bug原因是:ios7和ios8下要实现的代理方法是不同的
解决办法是:stackoverflow网站的建议如下:
意思就是如果是ios8,就是在ios的代理方法中调用ios7下的代理方法

Keep the old delegate method in place to support iOS 7 or earlier. What I do in my app is call the iOS 7 delegate method from the iOS 8 delegate method:

- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier {
    [self peoplePickerNavigationController:peoplePicker shouldContinueAfterSelectingPerson:person property:property identifier:identifier];
}

2015-03-25 20:59:06 u012103433 阅读数 260
//读取所有联系人


-(void)ReadAllPeoples


{
    
    //取得本地通信录名柄
    
    ABAddressBookRef tmpAddressBook = nil;
    
    if ([[UIDevice currentDevice].systemVersion floatValue]>=6.0) {
        tmpAddressBook=ABAddressBookCreateWithOptions(NULL, NULL);
        dispatch_semaphore_t sema=dispatch_semaphore_create(0);
        ABAddressBookRequestAccessWithCompletion(tmpAddressBook, ^(bool greanted, CFErrorRef error){
            dispatch_semaphore_signal(sema);
        });
    
    dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
    dispatch_release(sema);
    }
    else
    {
        tmpAddressBook =ABAddressBookCreate();
    }
    //取得本地所有联系人记录
    
    
    if (tmpAddressBook==nil) {
        return ;
    };
    NSArray* tmpPeoples = (NSArray*)ABAddressBookCopyArrayOfAllPeople(tmpAddressBook);
    
    for(id tmpPerson in tmpPeoples)
        
    {
        
        //获取的联系人单一属性:First name
        
        NSString* tmpFirstName = (NSString*)ABRecordCopyValue(tmpPerson, kABPersonFirstNameProperty);
        
        NSLog(@"First name:%@", tmpFirstName);
        
        [tmpFirstName release];
        
        //获取的联系人单一属性:Last name
        
        NSString* tmpLastName = (NSString*)ABRecordCopyValue(tmpPerson, kABPersonLastNameProperty);
        
        NSLog(@"Last name:%@", tmpLastName);
        
        [tmpLastName release];
        
        //获取的联系人单一属性:Nickname
        
        NSString* tmpNickname = (NSString*)ABRecordCopyValue(tmpPerson, kABPersonNicknameProperty);
        
        NSLog(@"Nickname:%@", tmpNickname);
        
        [tmpNickname release];
        
        //获取的联系人单一属性:Company name
        
        NSString* tmpCompanyname = (NSString*)ABRecordCopyValue(tmpPerson, kABPersonOrganizationProperty);
        
        NSLog(@"Company name:%@", tmpCompanyname);
        
        [tmpCompanyname release];
        
        //获取的联系人单一属性:Job Title
        
        NSString* tmpJobTitle= (NSString*)ABRecordCopyValue(tmpPerson, kABPersonJobTitleProperty);
        
        NSLog(@"Job Title:%@", tmpJobTitle);
        
        [tmpJobTitle release];
        
        //获取的联系人单一属性:Department name
        
        NSString* tmpDepartmentName = (NSString*)ABRecordCopyValue(tmpPerson, kABPersonDepartmentProperty);
        
        NSLog(@"Department name:%@", tmpDepartmentName);
        
        [tmpDepartmentName release];
        
        //获取的联系人单一属性:Email(s)
        
        ABMultiValueRef tmpEmails = ABRecordCopyValue(tmpPerson, kABPersonEmailProperty);
        
        for(NSInteger j = 0; ABMultiValueGetCount(tmpEmails); j++)
            
        {
            
            NSString* tmpEmailIndex = (NSString*)ABMultiValueCopyValueAtIndex(tmpEmails, j);
            
            NSLog(@"Emails%d:%@", j, tmpEmailIndex);
            
            [tmpEmailIndex release];
            
        }
        
        CFRelease(tmpEmails);
        
        //获取的联系人单一属性:Birthday
        
        NSDate* tmpBirthday = (NSDate*)ABRecordCopyValue(tmpPerson, kABPersonBirthdayProperty);
        
        NSLog(@"Birthday:%@", tmpBirthday);
        
        [tmpBirthday release];
        
        //获取的联系人单一属性:Note
        
        NSString* tmpNote = (NSString*)ABRecordCopyValue(tmpPerson, kABPersonNoteProperty);
        
        NSLog(@"Note:%@", tmpNote);
        
        [tmpNote release];
        
        //获取的联系人单一属性:Generic phone number
        
        ABMultiValueRef tmpPhones = ABRecordCopyValue(tmpPerson, kABPersonPhoneProperty);
        
        for(NSInteger j = 0; j < ABMultiValueGetCount(tmpPhones); j++)
            
        {
            
            NSString* tmpPhoneIndex = (NSString*)ABMultiValueCopyValueAtIndex(tmpPhones, j);
            
            NSLog(@"tmpPhoneIndex%d:%@", j, tmpPhoneIndex);
            
            [tmpPhoneIndex release];
            
        }
        
        CFRelease(tmpPhones);
        
    }
    
    //释放内存&nbsp;
    
    [tmpPeoples release];
    
    CFRelease(tmpAddressBook);
    

}

备注:

苹果中文语言貌似有点问题。ios6.0  会提示你的app访问日历。。。。
然后网上查了下资料。可以参照微信访问通讯录的形式,给客户一个提示
他是在plist中  添加一项在XCode里显示的是Privacy - Contacts Usage Description。后面的string就是你要想提示的文字内容
Privacy - Location Usage Description”。这个是定位位置提示。其他类似。

2016-12-02 16:48:28 ruanshibo 阅读数 232

苹果在iOS10更改了通讯的访问,之前的访问在没有开启权限的时候可能会报错,新版的使用如下



#define Is_up_Ios_9 [[UIDevice currentDevice].systemVersion floatValue] >= 9.0

// 之前的框架

#import "ContactsViewController.h"

#import <AddressBook/AddressBook.h>

#import <AddressBookUI/AddressBookUI.h>

/// iOS 9的新框架

#import <ContactsUI/ContactsUI.h>

@interface ContactsViewController ()<ABPeoplePickerNavigationControllerDelegate,CNContactPickerDelegate>

// 用于显示选中联系人的号码

@property (strong, nonatomic) IBOutlet UILabel *label;


@end


@implementation ContactsViewController


- (void)viewDidLoad {

    [super viewDidLoad];

    


    

}


- (IBAction)touch:(id)sender {//点击事件,打开通讯录

    

    ///获取通讯录权限,调用系统通讯录

    [self CheckAddressBookAuthorization:^(bool isAuthorized , bool isUp_ios_9) {

        if (isAuthorized) {

            [self callAddressBook:isUp_ios_9];

        }else {

            

            NSLog(@"请到设置>隐私>通讯录打开本应用的权限设置");

        }

    }];

}




- (void)CheckAddressBookAuthorization:(void (^)(bool isAuthorized , bool isUp_ios_9))block {


    

    

    if (Is_up_Ios_9){

        CNContactStore * contactStore = [[CNContactStore alloc]init];

        if ([CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts] == CNAuthorizationStatusNotDetermined) {

            [contactStore requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * __nullable error) {

                if (error)

                {

                    NSLog(@"Error: %@", error);

                }

                else if (!granted)

                {

                    

                    block(NO,YES);

                }

                else

                {

                    block(YES,YES);

                }

            }];

        }

        else if ([CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts] == CNAuthorizationStatusAuthorized){

            block(YES,YES);

        }

        else {

            NSLog(@"请到设置>隐私>通讯录打开本应用的权限设置");

        }

    }else {

        ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);

        ABAuthorizationStatus authStatus = ABAddressBookGetAuthorizationStatus();

        

        if (authStatus == kABAuthorizationStatusNotDetermined)

        {

            ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {

                dispatch_async(dispatch_get_main_queue(), ^{

                    if (error)

                    {

                        NSLog(@"Error: %@", (__bridge NSError *)error);

                    }

                    else if (!granted)

                    {

                        

                        block(NO,NO);

                    }

                    else

                    {

                        block(YES,NO);

                    }

                });

            });

        }else if (authStatus == kABAuthorizationStatusAuthorized)

        {

            block(YES,NO);

        }else {

            NSLog(@"请到设置>隐私>通讯录打开本应用的权限设置");

        }

    }

}

- (void)callAddressBook:(BOOL)isUp_ios_9 {

    if (isUp_ios_9) {

        CNContactPickerViewController *contactPicker = [[CNContactPickerViewController alloc] init];

        contactPicker.delegate = self;

        contactPicker.displayedPropertyKeys = @[CNContactPhoneNumbersKey];

        [self presentViewController:contactPicker animated:YES completion:nil];

    }else {

        ABPeoplePickerNavigationController *peoplePicker = [[ABPeoplePickerNavigationController alloc] init];

        peoplePicker.peoplePickerDelegate = self;

        [self presentViewController:peoplePicker animated:YES completion:nil];

        

    }

}


#pragma mark -- CNContactPickerDelegate

- (void)contactPicker:(CNContactPickerViewController *)picker didSelectContactProperty:(CNContactProperty *)contactProperty {

    CNPhoneNumber *phoneNumber = (CNPhoneNumber *)contactProperty.value;

    [self dismissViewControllerAnimated:YES completion:^{

        /// 联系人

        NSString *text1 = [NSString stringWithFormat:@"%@%@",contactProperty.contact.familyName,contactProperty.contact.givenName];

        /// 电话

        NSString *text2 = phoneNumber.stringValue;

        //        text2 = [text2 stringByReplacingOccurrencesOfString:@"-" withString:@""];

         _label.text = [NSString stringWithFormat:@"联系人:%@, 电话:%@",text1,text2];

        NSLog(@"联系人:%@, 电话:%@",text1,text2);

    }];

}


#pragma mark -- ABPeoplePickerNavigationControllerDelegate

- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController*)peoplePicker didSelectPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier {

    

    ABMultiValueRef valuesRef = ABRecordCopyValue(person, kABPersonPhoneProperty);

    CFIndex index = ABMultiValueGetIndexForIdentifier(valuesRef,identifier);

    CFStringRef value = ABMultiValueCopyValueAtIndex(valuesRef,index);

    CFStringRef anFullName = ABRecordCopyCompositeName(person);

    

    [self dismissViewControllerAnimated:YES completion:^{

        /// 联系人

        NSString *text1 = [NSString stringWithFormat:@"%@",anFullName];

        /// 电话

        NSString *text2 = (__bridge NSString*)value;

                text2 = [text2 stringByReplacingOccurrencesOfString:@"-" withString:@""];

        _label.text = [NSString stringWithFormat:@"联系人:%@, 电话:%@",text1,text2];

        NSLog(@"联系人:%@, 电话:%@",text1,text2);

    }];

}






运行效果如下








2013-08-22 09:32:08 DJY1992 阅读数 2934

    IOS开发笔记  IOS如何访问通讯录

其实我是反对这类的需求,你说你读我的隐私,我肯定不愿意的。
幸好ios6.0 以后给了个权限控制。当打开app的时候你可以选择拒绝。


实现方法:

[plain] view plaincopy
  1. //读取所有联系人  
  2.   
  3. -(void)ReadAllPeoples  
  4.   
  5. {  
  6.       
  7.     //取得本地通信录名柄  
  8.       
  9.     ABAddressBookRef tmpAddressBook = nil;  
  10.       
  11.     if ([[UIDevice currentDevice].systemVersion floatValue]>=6.0) {  
  12.         tmpAddressBook=ABAddressBookCreateWithOptions(NULL, NULL);  
  13.         dispatch_semaphore_t sema=dispatch_semaphore_create(0);  
  14.         ABAddressBookRequestAccessWithCompletion(tmpAddressBook, ^(bool greanted, CFErrorRef error){  
  15.             dispatch_semaphore_signal(sema);  
  16.         });  
  17.       
  18.     dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);  
  19.     dispatch_release(sema);  
  20.     }  
  21.     else  
  22.     {  
  23.         tmpAddressBook =ABAddressBookCreate();  
  24.     }  
  25.     //取得本地所有联系人记录  
  26.       
  27.       
  28.     if (tmpAddressBook==nil) {  
  29.         return ;  
  30.     };  
  31.     NSArray* tmpPeoples = (NSArray*)ABAddressBookCopyArrayOfAllPeople(tmpAddressBook);  
  32.       
  33.     for(id tmpPerson in tmpPeoples)  
  34.           
  35.     {  
  36.           
  37.         //获取的联系人单一属性:First name  
  38.           
  39.         NSString* tmpFirstName = (NSString*)ABRecordCopyValue(tmpPerson, kABPersonFirstNameProperty);  
  40.           
  41.         NSLog(@"First name:%@", tmpFirstName);  
  42.           
  43.         [tmpFirstName release];  
  44.           
  45.         //获取的联系人单一属性:Last name  
  46.           
  47.         NSString* tmpLastName = (NSString*)ABRecordCopyValue(tmpPerson, kABPersonLastNameProperty);  
  48.           
  49.         NSLog(@"Last name:%@", tmpLastName);  
  50.           
  51.         [tmpLastName release];  
  52.           
  53.         //获取的联系人单一属性:Nickname  
  54.           
  55.         NSString* tmpNickname = (NSString*)ABRecordCopyValue(tmpPerson, kABPersonNicknameProperty);  
  56.           
  57.         NSLog(@"Nickname:%@", tmpNickname);  
  58.           
  59.         [tmpNickname release];  
  60.           
  61.         //获取的联系人单一属性:Company name  
  62.           
  63.         NSString* tmpCompanyname = (NSString*)ABRecordCopyValue(tmpPerson, kABPersonOrganizationProperty);  
  64.           
  65.         NSLog(@"Company name:%@", tmpCompanyname);  
  66.           
  67.         [tmpCompanyname release];  
  68.           
  69.         //获取的联系人单一属性:Job Title  
  70.           
  71.         NSString* tmpJobTitle= (NSString*)ABRecordCopyValue(tmpPerson, kABPersonJobTitleProperty);  
  72.           
  73.         NSLog(@"Job Title:%@", tmpJobTitle);  
  74.           
  75.         [tmpJobTitle release];  
  76.           
  77.         //获取的联系人单一属性:Department name  
  78.           
  79.         NSString* tmpDepartmentName = (NSString*)ABRecordCopyValue(tmpPerson, kABPersonDepartmentProperty);  
  80.           
  81.         NSLog(@"Department name:%@", tmpDepartmentName);  
  82.           
  83.         [tmpDepartmentName release];  
  84.           
  85.         //获取的联系人单一属性:Email(s)  
  86.           
  87.         ABMultiValueRef tmpEmails = ABRecordCopyValue(tmpPerson, kABPersonEmailProperty);  
  88.           
  89.         for(NSInteger j = 0; ABMultiValueGetCount(tmpEmails); j++)  
  90.               
  91.         {  
  92.               
  93.             NSString* tmpEmailIndex = (NSString*)ABMultiValueCopyValueAtIndex(tmpEmails, j);  
  94.               
  95.             NSLog(@"Emails%d:%@", j, tmpEmailIndex);  
  96.               
  97.             [tmpEmailIndex release];  
  98.               
  99.         }  
  100.           
  101.         CFRelease(tmpEmails);  
  102.           
  103.         //获取的联系人单一属性:Birthday  
  104.           
  105.         NSDate* tmpBirthday = (NSDate*)ABRecordCopyValue(tmpPerson, kABPersonBirthdayProperty);  
  106.           
  107.         NSLog(@"Birthday:%@", tmpBirthday);  
  108.           
  109.         [tmpBirthday release];  
  110.           
  111.         //获取的联系人单一属性:Note  
  112.           
  113.         NSString* tmpNote = (NSString*)ABRecordCopyValue(tmpPerson, kABPersonNoteProperty);  
  114.           
  115.         NSLog(@"Note:%@", tmpNote);  
  116.           
  117.         [tmpNote release];  
  118.           
  119.         //获取的联系人单一属性:Generic phone number  
  120.           
  121.         ABMultiValueRef tmpPhones = ABRecordCopyValue(tmpPerson, kABPersonPhoneProperty);  
  122.           
  123.         for(NSInteger j = 0; j < ABMultiValueGetCount(tmpPhones); j++)  
  124.               
  125.         {  
  126.               
  127.             NSString* tmpPhoneIndex = (NSString*)ABMultiValueCopyValueAtIndex(tmpPhones, j);  
  128.               
  129.             NSLog(@"tmpPhoneIndex%d:%@", j, tmpPhoneIndex);  
  130.               
  131.             [tmpPhoneIndex release];  
  132.               
  133.         }  
  134.           
  135.         CFRelease(tmpPhones);  
  136.           
  137.     }  
  138.       
  139.     //释放内存   
  140.       
  141.     [tmpPeoples release];  
  142.       
  143.     CFRelease(tmpAddressBook);  
  144.       
  145. }  

解释下代码:由于ios6.0系统的升级,对客户隐私有了一个较大的提示。
以前
[plain] view plaincopy
  1. tmpAddressBook =ABAddressBookCreate();这样就可以读取了,但是现在要做一个判断了。可以具体看看代码。  
[plain] view plaincopy
  1. 把通讯录取出来放在一个array里面。这样你就可以对数组进行你的要求了。  
[plain] view plaincopy
  1.   

备注:

苹果中文语言貌似有点问题。ios6.0  会提示你的app访问日历。。。。
然后网上查了下资料。可以参照微信访问通讯录的形式,给客户一个提示
他是在plist中  添加一项在XCode里显示的是Privacy - Contacts Usage Description。后面的string就是你要想提示的文字内容
Privacy - Location Usage Description”。这个是定位位置提示。其他类似。

备注二:

分享一个测试经验,也是从网上看到的。
一把苹果的app访问位置或者通讯录,第一次都会有一个提示让你选择。
但是第二次及以后,即时删掉,也不会再出现了。
如果想再次出现,可以  设置-通用-还原-还原位置与隐私
这样你再次点击你的app就会再次出现了。


2015-03-07 15:14:16 w250130255 阅读数 459

最近做了个项目要求  访问用户的通讯录并且针对通讯录里的数据进行筛选,基于现有的IM用户体系,进行邀请添加聊天。


首先用户通讯录信息 作为重要的隐私,访问通讯录 在IOS6 以上版本 是必须经过用户同意,才可以访问。

ABAddressBookRef addressBook =NULL;
    
    if([[UIDevice currentDevice].systemVersion floatValue] >= 6.0){
        
        CFErrorRef error = NULL;
        
        addressBook =ABAddressBookCreateWithOptions(NULL, &error);
        
        ABAuthorizationStatus authorizationStatus =ABAddressBookGetAuthorizationStatus();
        
        
        
        //        dispatch_semaphore_t sema = dispatch_semaphore_create(0);
        
        if(authorizationStatus ==kABAuthorizationStatusNotDetermined){
            
            ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted,CFErrorRef error) {
                
                if(granted)
                    
                    
                    
                    NSLog(@"授权");
                
                else
                    
                    NSLog(@"拒绝");
                
                //                dispatch_semaphore_signal(sema);
                
            });
            
            //            dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
            
        }
        
    }
    
    else
        
    {
        
        addressBook =ABAddressBookCreate();
        
    }

- (BOOL) application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions


如果以上代码放在AppDelegate里,程序在第一次启动的时候会进行提示 “是否允许访问通讯录功能


iOS 访问通讯录

阅读数 798

iOS 通讯录基础

阅读数 1018

没有更多推荐了,返回首页