iOS系統通訊錄授權,獲取,修改,創建聯繫人

1、現在的很多應用程序中都會設計到手機系統通訊錄的問題,下面就簡單介紹一下iOS系統通訊錄的
2、iOS9之前的系統通訊錄有2個框架,分別是AddressBookUI/AddressBookUI.h // 系統帶UI通訊錄, AddressBook/AddressBook.h // 系統通訊錄,需要自己手動搭建頁面,
3、 AddressBookUI/AddressBookUI.h // 系統帶UI通訊錄,不用自己搭建頁面,直接調用系統的就可以了,

ABPeoplePickerNavigationController *vc = [[ABPeoplePickerNavigationController alloc] init];
    vc.peoplePickerDelegate = self;

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

遵守代理ABPeoplePickerNavigationControllerDelegate,並實現代理方法:

// ios7
- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker{
    NSLog(@"111111");
    [peoplePicker dismissViewControllerAnimated:YES completion:nil];
}

// 在iOS7中選中一個聯繫人就會調用
// 返回一個BOOL值,NO代表不會進入到下一層(詳情),YES代表會進入到下一層
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person{
    return NO;
}

// ios8選中一個聯繫人就會調用 實現這個方法之後,控制器不會進入到下一層(詳情),直接dismiss
//- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person{
//    NSLog(@"2222");
//}

// ios8選中某一個聯繫人的某一個屬性時就會調用
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier{
    NSLog(@"%@,%d,@%d",person,property,identifier);
}

這樣的話,就能夠直接利用系統的通訊錄界面進行操作了,但是有一點就是,不能在界面上操作需求。

4、獲取聯繫人。
AddressBook/AddressBook.h // 系統通訊錄,需要自己手動搭建頁面,這個框架只能夠通過手動拿到聯繫人數據,然後自己搭建界面展示數據,並可以進行其他的需求操作。

(1)爲了更方便的展示數據,首先創建person模型類:PeopleModel

#import <UIKit/UIKit.h>
@interface PeopleModel : NSObject

@property (nonatomic, copy) NSString *name; // 姓名
@property (nonatomic, copy) NSString *email; // 郵箱
@property (nonatomic, copy) NSString *tellPhone; // 電話
@property (nonatomic, strong) UIImage *iconImage; // 聯繫人頭像

@property (nonatomic, assign) NSInteger sectionNumber; // section標題(用於按某一個屬性排序,比如按照name排序)
@end

從通訊錄中獲取所有的聯繫人,並轉換成person模型類,
(2)首先創建數據源,數據源一定要初始化,很多時候忘記初始化數據源會導致看不到數據,

@property (nonatomic ,retain) NSMutableArray *peoplePhoneData; // 用來存儲聯繫人(分組)

// self.peoplePhoneData = [NSMutableArray array]; // 記得初始化數據源(這裏就不用懶加載了)

(3)取得通訊錄授權:程序在第一次使用的時候,會請求用戶的授權,如果用戶同意了,就加載數據,拒絕了,就給提示。如果不是第一次使用通訊錄,就不再提示授權的提示框,但程序同樣要走到下面的請求函數,這時系統會自動識別授權狀態,granted=1,就是已經授權的,granted=0就是拒絕授權或者其他的,總之只有同意授權纔可以拿數據的。

CFErrorRef *error = nil;

    ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(nil, error);
    ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
        NSLog(@"granted==%d",granted);

        if (granted) {
            NSLog(@"授權成功!");
            [self getUpAddBookViewPersonDataWithAddBook:addressBook];
        } else {
            NSLog(@"授權失敗!");
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"授權失敗" message:@"請在設置中打開訪問權限" delegate:nil cancelButtonTitle:@"取消" otherButtonTitles:@"確定", nil];
            [alert show];
        }

    });

獲取授權狀態也可以用ABAddressBookGetAuthorizationStatus()獲取授權狀態,

kABAuthorizationStatusNotDetermined = 0, // 還沒有決定是否授權(就是在第一次提示授權的時候)
kABAuthorizationStatusRestricted, // 有其他限制通訊錄授權的狀態
kABAuthorizationStatusDenied, // 拒絕授權
kABAuthorizationStatusAuthorized // 同意授權
(4)獲取所有聯繫人並按照拼音排序(效果就是系統通訊錄的排序效果),都是c語言的語法,與oc轉化的時候是通過__bridge(橋接)來互相轉換的

// 獲取所有聯繫人並存儲
- (void)getUpAddBookViewPersonDataWithAddBook:(ABAddressBookRef)addressBook
{
    // 獲取所有聯繫人並存儲
    CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
    CFIndex peolpeCount = ABAddressBookGetPersonCount(addressBook); // 獲取聯繫人個數

    NSMutableArray *peopleArray = [NSMutableArray array]; // 用來存儲聯繫人模型

    // 獲取聯繫人信息(將聯繫人轉模型)
    for (NSInteger i = 0; i < peolpeCount; i++)
    {
        PeopleModel *model = [[PeopleModel alloc] init];
        ABRecordRef person = CFArrayGetValueAtIndex(allPeople, i); // 獲取某一個聯繫人
        CFStringRef firstName = ABRecordCopyValue(person, kABPersonFirstNameProperty);
        CFStringRef lastName = ABRecordCopyValue(person, kABPersonLastNameProperty);
        CFStringRef fullName = ABRecordCopyCompositeName(person);


//         取出個人記錄中的詳細信息
//        NSString *firstNameLabel = (__bridge NSString *)(ABPersonCopyLocalizedPropertyName(kABPersonFirstNameProperty));
//        NSString *firstName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonFirstNameProperty));
//        NSString *lastNameLabel = (__bridge NSString *)(ABPersonCopyLocalizedPropertyName(kABPersonLastNameProperty));
//        NSString *lastName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonLastNameProperty));
//        NSLog(@"%@ %@ - %@ %@", lastNameLabel, lastName, firstNameLabel, firstName);


        // 讀取name
        NSString *firstNameStr = (__bridge NSString *)firstName;
        NSString *lastNameStr = (__bridge NSString *)lastName;
        NSString *fullNameStr = (__bridge NSString *)fullName;

        if ( fullNameStr.length != 0) {
            firstNameStr = fullNameStr;
        } else if (lastNameStr.length!=0) {
            firstNameStr = [NSString stringWithFormat:@"%@ %@",firstNameStr,lastNameStr];
        }
        model.name = firstNameStr;
        // 讀取郵箱
        ABMultiValueRef email = ABRecordCopyValue(person, kABPersonEmailProperty);
        NSInteger emailCount = ABMultiValueGetCount(email);
        for (NSInteger i = 0; i < emailCount; i++) {
            model.email = (__bridge NSString *)ABMultiValueCopyValueAtIndex(email, i);
        }

        // 讀取電話
        ABMultiValueRef tellPhone = ABRecordCopyValue(person, kABPersonPhoneProperty);
        for (NSInteger i = 0; i < ABMultiValueGetCount(tellPhone); i++) {
            model.tellPhone = (__bridge NSString *)ABMultiValueCopyValueAtIndex(tellPhone, i);
        }


//        for (NSInteger i = 0; i < ABMultiValueGetCount(tellPhone); i++) {
////            獲取複雜屬性的方法
//            // 電話標籤
//            CFStringRef phoneLabel = ABMultiValueCopyLabelAtIndex(tellPhone, i);
//            // 本地化電話標籤
//            CFStringRef phoneLocalLabel = ABAddressBookCopyLocalizedLabel(phoneLabel);
//            // 電話號碼 
//            CFStringRef phoneNumber = ABMultiValueCopyValueAtIndex(tellPhone, i);
//        }

        // 讀取聯繫人頭像
        NSData *iconData = (__bridge NSData *)ABPersonCopyImageData(person);
        model.iconImage = [UIImage imageWithData:iconData];

        [peopleArray addObject:model];
        if (firstName) {
            CFRelease(firstName);
        }
        if (lastName) {
            CFRelease(lastName);
        }
        if (fullName) {
            CFRelease(fullName);
        }

        CFRelease(email);
        CFRelease(tellPhone);
    }

    // 排序
    UILocalizedIndexedCollation *theCollation = [UILocalizedIndexedCollation currentCollation];
    for (PeopleModel *model in peopleArray) {
        NSInteger sect = [theCollation sectionForObject:model
                                collationStringSelector:@selector(name)]; // 根據模型的name字斷排序
        model.sectionNumber = sect;
    }

    NSInteger highSection = [[theCollation sectionTitles] count];

    NSMutableArray *sectionArrays = [NSMutableArray arrayWithCapacity:highSection];

    for (int i=0; i<=highSection; i++) {
        NSMutableArray *sectionArray = [NSMutableArray arrayWithCapacity:1];
        [sectionArrays addObject:sectionArray];
    }

    for (PeopleModel *model in peopleArray) {
        [(NSMutableArray *)[sectionArrays objectAtIndex:model.sectionNumber] addObject:model];
    }

    // 排好序的聯繫人加入數組中
    for (NSMutableArray *sectionArray in sectionArrays) {
        int count = 0; // 統計name爲nil的個數
        for (PeopleModel *model in sectionArray) {
            if (model.name.length==0) {
                count++;
            }
        }
        NSArray *sortedSection = [NSArray array];
        //        NSArray *sortedSection = [theCollation sortedArrayFromArray:sectionArray collationStringSelector:@selector(name)];
        if (count >= 2) { // 有2個以上name爲nil,
            sortedSection = [NSArray arrayWithArray:sectionArray];
        } else {
            sortedSection = [theCollation sortedArrayFromArray:sectionArray collationStringSelector:@selector(name)];
        }
        [self.peoplePhoneData addObject:sortedSection];
    }
    [self.tableView reloadData];
}

在iOS的通訊錄中的聯繫人的名字是有好幾個的(firstName,lastName,fullName),所有按照需求來操作,並且手機號,郵箱都是有多個的,所有這些需求就需要按照設計需求來做了。

(5)索引實現。

// 索引序列
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
    tableView.sectionIndexColor = [UIColor redColor];
    tableView.sectionIndexBackgroundColor=[UIColor clearColor];
    NSArray * array=[[NSArray arrayWithObject:@"★"] arrayByAddingObjectsFromArray:[[UILocalizedIndexedCollation currentCollation] sectionIndexTitles]];
    return [[NSArray arrayWithObject:UITableViewIndexSearch] arrayByAddingObjectsFromArray:array];
}

(6)section title
- (NSString )tableView:(UITableView )tableView titleForHeaderInSection:(NSInteger)section
{

NSString *title = [self.peoplePhoneData[section] count] ? [[[UILocalizedIndexedCollation currentCollation] sectionTitles] objectAtIndex:section]:nil;
return title;

}

5、修改聯繫人

// 修改聯繫人
- (void)updateRecod{

    // 1. 拿到通訊錄
    ABAddressBookRef book = ABAddressBookCreateWithOptions(NULL, NULL);

    // 獲取通訊錄所有人
    CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(book);

    // 拿到通訊錄中的某一個聯繫人
    ABRecordRef people = CFArrayGetValueAtIndex(allPeople, 0);

    // 修改聯繫人信息
    ABRecordSetValue(people, kABPersonLastNameProperty, @"Li", NULL);

    // 保存通訊錄
    ABAddressBookSave(book, NULL);


//    ABPersonHasImageData(people); // 判斷通訊錄中的聯繫人是否有圖片
//    ABPersonSetImageData(people, <#CFDataRef imageData#>, <#CFErrorRef *error#>); // 設置聯繫人的圖片數據

//    ABAddressBookRemoveRecord(<#ABAddressBookRef addressBook#>, <#ABRecordRef record#>, <#CFErrorRef *error#>) // 刪除某一個聯繫人

//    ABAddressBookRevert(<#ABAddressBookRef addressBook#>) // 放棄更改信息
//    ABAddressBookHasUnsavedChanges(<#ABAddressBookRef addressBook#>) // 函數判斷是否有未保存的修改
}

5、添加新的聯繫人

// 添加聯繫人
- (void)creadRecod{
    // 1. 創建聯繫人
    ABRecordRef people = ABPersonCreate();

    // 2. 設置聯繫人信息
    ABRecordSetValue(people, kABPersonLastNameProperty, @"san", NULL);
    ABRecordSetValue(people, kABPersonFirstNameProperty, @"zhang", NULL);

    // 創建電話號碼
    ABMultiValueRef phones = ABMultiValueCreateMutable(kABMultiStringPropertyType);
    ABMultiValueAddValueAndLabel(phones, @"123456789", kABPersonPhoneMainLabel, NULL);
    ABMultiValueAddValueAndLabel(phones, @"888888", kABPersonPhoneHomeFAXLabel, NULL);

    ABRecordSetValue(people, kABPersonPhoneProperty, phones, NULL);

    // 3. 拿到通訊錄
    ABAddressBookRef book = ABAddressBookCreateWithOptions(NULL, NULL);

    // 4. 將聯繫人添加到通訊錄中
    ABAddressBookAddRecord(book, people, NULL);

    // 5. 保存通訊錄
    ABAddressBookSave(book, NULL);
}

6、聯繫人的操作基本上就那麼多了,有一些屬性值是沒有涉及到的,但是基本的操作方法都差不多。但是在iOS9之後,系統的通訊錄框架改成了 ContactsUI/ContactsUI.h,這個後期會研究一下,並發表出來。

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