iOS 獲取通訊錄相關信息

//由於本人閒來無事,爲了打發時間,把以前項目的中一些知識點整理一下,下面是 獲取通訊錄的相關知識點,內容簡單,希望對各位有所幫助,有何問題,歡迎留言(PS:雖然不一定回覆您或者幫您解決,但好歹您老人家不要憋壞了)


/**

 *獲取通訊錄信息

 倒入頭文件 #import <AddressBook/AddressBook.h>

 build phases 裏面 導入 addressBook.framework 框架


 

 *隨着apple對用戶隱私的越來越重視,IOS系統的權限設置也更加嚴格,在獲取系統通訊錄之前,我們必須獲得用戶的授權。權限申請代碼示例如下:

 *參考博客://http://www.open-open.com/code/view/1432302834146

 */


//授權 :如果不授權 是讀不出通訊錄信息的

- (void)getInfoOfAddressBookWithAuthorize

{

    //這個變量用於記錄授權是否成功,即用戶是否允許我們訪問通訊錄

    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)        {

            //greantedYES是表示用戶允許,否則爲不允許

            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;

    }

    /*

     幾點注意:1dispatch_semaphore_t三個相關的操作爲

     

     dispatch_semaphore_create 創建一個信號

     dispatch_semaphore_signal 發送一個信號

     dispatch_semaphore_wait               等待信號觸發

     

     dispatch_semaphore_create()創建一個信號,後面可以跟一個參數,表示信號量,當信號量正值時,dispatch_semaphore_wait後面的代碼會被執行,否則程序將會一直等待在dispatch_semaphore_wait dispatch_semaphore_signal的作用是發送一個信號,會使信號量加1,相對的,dispatch_semaphore_wait執行後會使信號量減1.

     

     2、因爲是否被授權是在ABAddressBookRequestAccessWithCompletionblock回調中獲取的,所以我們需要在外面做一個線程等待

     */

//    [self writeContractPerson:addBook];

    

    [self deleteInfo:addBook];

    [self addressBookMessager:addBook];

    

    CFRelease(addBook);

}


/*

 *  四、重中之重-關於內存管理

    上面的代碼爲了演示方便,創建的全部引用都沒有釋放,勢必是造成內存泄露,在我們用ABAddressBookCreate()創建一個引用對象時,切記無論ARCMRC,要用CFRelease()進行釋放引用,例如上面的例子,我們需要加上這句代碼

    CFRelease(addBook);

    如果你耐心的看到了這裏,我想你一定明白了我爲什麼不在前邊的代碼裏說明這個問題,因爲在ARC項目普及的現在,這的確是重中之重。

 */


// 獲取通訊錄信息

- (void)addressBookMessager:(ABAddressBookRef )addBook

{

    //隨着apple對用戶隱私的越來越重視,IOS系統的權限設置也更加嚴格,在獲取系統通訊錄之前,我們必須獲得用戶的授權。權限申請代碼示例如下:

    NSString *allName = nil;

    //獲取所有聯繫人的數組

    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));

        //獲取當前聯繫人的生日

        NSDate*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++) {

            [phoneArr addObject:(__bridge NSString *)(ABMultiValueCopyValueAtIndex(phones, j))];

        }

        

        /*

         *對我需要的數據進行處理,這個自己去加以判斷選擇

         */

        if (firstName == nil && middleName == nil && lastName == nil) {

            allName = [phoneArr firstObject];

        }else {//如果沒有名字的時候,在通訊錄裏面用電話號碼去顯示

            if (firstName == nil) {

                firstName = @"";

            }

            if (lastName == nil) {

                lastName = @"";

            }

            if (middleName == nil) {

                middleName = @"";

            }

            allName = [NSString stringWithFormat:@"%@%@%@",firstName,middleName,lastName];

        }

        

        [self.dataList addObject:allName];

        

        

        //獲取創建當前聯繫人的時間 注意是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];

        }

    }

    

    /*

     * 一定要釋放內存

     */

    CFRelease(allLinkPeople);

}


/**

 *通訊錄的相關操作

 */

- (void)writeContractPerson:(ABAddressBookRef )addBook {


    //創建一個聯繫人引用

    ABRecordRef person = ABPersonCreate();

    NSString *firstName = @"1";

    NSString *lastName = @"1";

    NSData *birthday = nil;

    // 電話號碼數組

    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);

    

    

    CFRelease(person);


    /*

     *2、修改聯繫人

     *   修改聯繫人的操作就是將獲取和添加和在一起,先獲取到相應的聯繫人引用,重設其屬性字段即可。

     */

}

//刪除聯繫人

- (void)deleteInfo:(ABAddressBookRef )addBook {


    //獲取所有聯繫人

    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);

}



/*

 場景一:直接選擇一個聯繫人的電話號碼《這種情景時彈出一個系統的VC,然後可以去選擇通訊錄一條信息,點擊後有回彈出一個VC,您在選擇後,可以獲取相關聯繫人的信息,這時他會自動的反悔到上個頁面,可以按返回按鈕,回到最初您寫的的頁面》您可以在 協議方法裏面做一些相關的處理

 這裏不需要先獲取所有的聯繫人自己做聯繫人列表,直接使用系統自帶的AddressBookUI/ABPeoplePickerNavigationController.h就好。

 

 首先需要引入如下三個文件

 

 #import <AddressBookUI/ABPeoplePickerNavigationController.h>

 #import <AddressBook/ABPerson.h>

 #import <AddressBookUI/ABPersonViewController.h>

 

 然後初始化ABPeoplePickerNavigationController

 

 協議方法

 - (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController*)peoplePicker didSelectPerson:(ABRecordRef)person NS_AVAILABLE_IOS(8_0);

 

 // Called after a property has been selected by the user.

 - (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController*)peoplePicker didSelectPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier NS_AVAILABLE_IOS(8_0);

 

 // Called after the user has pressed cancel.

 - (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker;

 

 

 // Deprecated, use predicateForSelectionOfPerson and/or -peoplePickerNavigationController:didSelectPerson: instead.

 - (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person NS_DEPRECATED_IOS(2_0, 8_0);

 

 // Deprecated, use predicateForSelectionOfProperty and/or -peoplePickerNavigationController:didSelectPerson:property:identifier: instead.

 - (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier NS_DEPRECATED_IOS(2_0, 8_0);

 

 */


- (void)memorandum {

    

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

    nav.peoplePickerDelegate = self;

    if([[UIDevice currentDevice].systemVersion floatValue] >= 8.0){

        nav.predicateForSelectionOfPerson = [NSPredicate predicateWithValue:false];

    }

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

    /*

     iOS8之後,需要添加nav.predicateForSelectionOfPerson = [NSPredicate predicateWithValue:false];這一段代碼,否則選擇聯繫人之後會直接dismiss,不能進入詳情選擇電話。

     */

}


//取消選擇  用戶按下取消後調用。

- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker

{

    [peoplePicker dismissViewControllerAnimated:YES completion:nil];

}


//iOS8

// Called after a person has been selected by the user .一個人被選中的人被用戶選中。

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

    ABMultiValueRef phone = ABRecordCopyValue(person, kABPersonPhoneProperty);

    long index = ABMultiValueGetIndexForIdentifier(phone,identifier);

    NSString *phoneNO = (__bridge NSString *)ABMultiValueCopyValueAtIndex(phone, index);

    

    if ([phoneNO hasPrefix:@"+"]) {

        phoneNO = [phoneNO substringFromIndex:3];

    }

    

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

    NSLog(@"%@", phoneNO);

//    if (phone && [ZXValidateHelper checkTel:phoneNO]) {

//        phoneNum = phoneNO;

//        [self.tableView reloadData];

//        [peoplePicker dismissViewControllerAnimated:YES completion:nil];

//        return;

//    }

}


//一個人被選中的人被用戶選中。

- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController*)peoplePicker didSelectPerson:(ABRecordRef)person

{

    ABPersonViewController *personViewController = [[ABPersonViewController alloc] init];

    personViewController.displayedPerson = person;

    [peoplePicker pushViewController:personViewController animated:YES];

}


// ios 7

- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person

{

    return YES;

}


- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier

{

    ABMultiValueRef phone = ABRecordCopyValue(person, kABPersonPhoneProperty);

    long index = ABMultiValueGetIndexForIdentifier(phone,identifier);

    NSString *phoneNO = (__bridge NSString *)ABMultiValueCopyValueAtIndex(phone, index);

    if ([phoneNO hasPrefix:@"+"]) {

        phoneNO = [phoneNO substringFromIndex:3];

    }

    

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

    NSLog(@"%@", phoneNO);

//    if (phone && [ZXValidateHelper checkTel:phoneNO]) {

//        phoneNum = phoneNO;

//        [self.tableView reloadData];

//        [peoplePicker dismissViewControllerAnimated:YES completion:nil];

//        return NO;

//    }

    return YES;

}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章