IOSについてローカルレコード情報を取得する(iOS 9.0前後を含む)

6774 ワード

blog:developfan.com
簡単な本:http://www.jianshu.com/u/9fed08d0ebfb   
ios開発では,ユーザのローカルの通信録を取得する機能がますます頻繁に出現し,七両自身も自社のプロジェクトで出会ったローカルの通信録情報を取得する機能(通称「シードユーザ機能」,恐ろしい).これに対して七両は、自分がローカルの通信録を使っているときの注意点をまとめ、皆さんの役に立つことを願っています.
まず、ローカルの通信録を取得する情報について、アップルはios 9.0の後に別の使用方法(controller)を発表し、前のsearchcontrollerとsearchBarに似ている.この7つの部分はここで2つの部分に分けられ、ios 9.0の前とios 9.0の後の2つの部分にまとめられている.
一、iOS 9.0前
まず七両の自分で書いたコードを添付します.
アップルの通信録に対する操作実装は、sqliteとsqlite 3の管理実装方式を類比することができ、通信録を使用する際にsqlite 3のような管理オブジェクトを呼び出す必要がある.
自分の習慣は通信録の操作過程を単例に書き、具体的には以下の通りである.
.hファイル
#import 
#import 
#import 

typedef void(^YFAddressBookBlock)(BOOL canRead, ABAuthorizationStatus authorStatus);

@interface YFAddressBookManger : NSObject

@property (nonatomic, assign) ABAddressBookRef addressBook;
//     
+ (instancetype)shareManger;

//    
- (void)canReadAddressBookWithBlock:(YFAddressBookBlock)block;

- (void)gotoSetting:(UIViewController *)vc;

@end

.mファイル
#import "YFAddressBookManger.h"

@implementation YFAddressBookManger

+ (instancetype)shareManger{
    static YFAddressBookManger *manger = nil;

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (!manger) {
            manger = [[YFAddressBookManger alloc]init];
        }
    });
    return manger;
}

- (id)init{
    self = [super init];
    if (self) {
        _addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
    }
    
    return self;
}

//      
- (void)canReadAddressBookWithBlock:(YFAddressBookBlock)block{
    ABAuthorizationStatus authStatus = ABAddressBookGetAuthorizationStatus();
    if (authStatus == kABAuthorizationStatusNotDetermined) {
        ABAddressBookRequestAccessWithCompletion(_addressBook, ^(bool granted, CFErrorRef error) {
           dispatch_async(dispatch_get_main_queue(), ^{
               if (error) {
                   //    
                   block(NO,kABAuthorizationStatusDenied);
               }else{
                   block(YES,0);
               }
           });
        });
    }else if (authStatus == kABAuthorizationStatusAuthorized){
        block(YES,0);
    }else{
        block(NO,authStatus);
    }
}

//     
- (void)gotoSetting:(UIViewController *)vc{
    NSString *appName = [[NSBundle mainBundle].infoDictionary valueForKey:@"CFBundleDisplayName"];
    if (!appName) appName = [[NSBundle mainBundle].infoDictionary valueForKey:@"CFBundleName"];
    NSString *message = [NSString stringWithFormat:@"  %@ \"  -  -   \"   ,\r  %@       。",[UIDevice currentDevice].model,appName];

    UIAlertController *alertVC = [[UIAlertController alloc]init];
    [UIAlertController alertControllerWithTitle:@"  " message:message preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction *sureAction = [UIAlertAction actionWithTitle:@"  " style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
    }];
    UIAlertAction *cancleAction = [UIAlertAction actionWithTitle:@"  " style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        
    }];
    [alertVC addAction:cancleAction];
    [alertVC addAction:sureAction];
}
@end

その後、通信録のデータをcontrollerに参照する方法は以下の通りです.
#pragma mark -           
- (void)getDataSource{
    if (_dataSource == nil) {
        _dataSource = [NSMutableArray new];
    }
    [[YFAddressBookManger shareManger]canReadAddressBookWithBlock:^(BOOL canRead, ABAuthorizationStatus authorStatus) {
        if (canRead) {
            ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
            CFArrayRef allLinkPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
            CFIndex num = ABAddressBookGetPersonCount(addressBook);
            for (NSInteger i = 0; i < num; i++) {
                ABRecordRef  people = CFArrayGetValueAtIndex(allLinkPeople, i);
                ABMultiValueRef phones = ABRecordCopyValue(people, kABPersonPhoneProperty);
                
                for (int k = 0; k

残りの余分な単一値属性に異なるフィールドが必要な場合、コードのABRecordCopyValueメソッドはC言語の辞書として理解できます.を選択します.
二、iOS 9.0以降
アップルはContactsUIの使用を推奨し、具体的な使用方法は以下の通りである.
pragma mark - 
/*          ,       
@param picker           
@param contact        /
(void)contactPicker:(CNContactPickerViewController )picker didSelectContact:(CNContact )contact{
// 1.           NSString *firstName = contact.givenName;
  NSString *lastName = contact.familyName;
  NSLog(@"%@ %@", firstName, lastName);
// 2.             NSArray *phoneNumers = contact.phoneNumbers;
   for (CNLabeledValue *labelValue in phoneNumers) {
       CNPhoneNumber *phoneNumber = labelValue.value; 
       NSString *phoneValue = phoneNumber.stringValue; 
       NSString *phoneLabel = labelValue.label;
       NSLog(@"%@ %@", phoneValue, phoneLabel);
  }
}
/*                 ,       
@param contactProperty         
*/
(void)contactPicker:(CNContactPickerViewController )picker didSelectContactProperty:(CNContactProperty )contactProperty{}

詳細は次のとおりです.
// 1.      
CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
// 2.        ,     
if (status != CNAuthorizationStatusAuthorized) return;

// 3.     
// 3.1.       
CNContactStore *store = [[CNContactStore alloc] init];

// 3.2.          
// keys           ,    /  
NSArray *fetchKeys = @[CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey];
CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:fetchKeys];

// 3.3.     
NSError *error = nil;
[store enumerateContactsWithFetchRequest:request error:&error usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop) {
    // stop        
    // 1.    
    NSString *firstname = contact.givenName;
    NSString *lastname = contact.familyName;
    NSLog(@"%@ %@", firstname, lastname);

    // 2.      
    NSArray *phones = contact.phoneNumbers;

    // 3.      
    for (CNLabeledValue *labelValue in phones) {
        CNPhoneNumber *phoneNumber = labelValue.value;
        NSLog(@"%@ %@", phoneNumber.stringValue, labelValue.label);
    }
}];