iOS獲取通訊錄

獲取通訊錄

有的時候我們需要獲取用戶的通訊錄信息上傳給服務器,對於iOS來說iOS9之前和之後有不同的方法用於獲取通訊錄信息。

iOS9之前

在9之前的版本獲取通訊錄信息是通過ABAddressBookCopyArrayOfAllPeople 來獲取所有聯繫人的信息的。所有的聯繫人信息被保存在一個數組裏面,我們只需要遍歷整個數組就可以獲取我們想要的信息的。下面以獲取所有聯繫人的姓名和電話號碼和唯一識別碼爲例,提供一個簡單的函數:

- (void)accessABAddressBook:(ABAddressBookRef)addressBookRef andResult:(void(^)(NSArray * models))completionHandler {
    CFArrayRef arrayRef = ABAddressBookCopyArrayOfAllPeople(addressBookRef);
    NSMutableArray *mutableArray = [[NSMutableArray alloc] init];
    for (int i = 0; i< CFArrayGetCount(arrayRef); i++) {
        ABRecordRef people = CFArrayGetValueAtIndex(arrayRef, i);
        NSString *identify = [NSString stringWithFormat:@"%d",ABRecordGetRecordID(people)];
        NSString *firstName = (__bridge NSString *)(ABRecordCopyValue(people, kABPersonFirstNameProperty));
        NSString *lastName = (__bridge NSString *)(ABRecordCopyValue(people, kABPersonLastNameProperty));
        NSString *name = [[NSString alloc] init];
        if (firstName) {
            name = [name stringByAppendingString:firstName];
        }
        if (lastName) {
            name = [name stringByAppendingString:lastName];
        }

        ABMutableMultiValueRef  phonesArray = ABRecordCopyValue(people, kABPersonPhoneProperty);
        NSString *phoneNumber = @"";
        for (int j = 0; j < ABMultiValueGetCount(phonesArray); j++) {
            NSString *phone = (__bridge NSString *)(ABMultiValueCopyValueAtIndex(phonesArray, j));
            if (phone) {
                phone = [phone stringByAppendingString:@";"];
                phoneNumber = [phoneNumber stringByAppendingString:phone];
            }

        }
        if([phoneNumber isEqualToString:@""]) {
            continue;
        }
        NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:name,@"desc",phoneNumber,@"phoneNo",identify,@"deviceRecordId", nil];
        [mutableArray addObject:dic];
    }
    completionHandler([mutableArray copy]);
}

iOS9之後

在iOS9之後,蘋果爲方便獲取通訊錄提供了一套API,開發者可以通過CNContactStore 這個類獲取需要的信息,這個類有個實例方法:enumerateContactsWithFetchRequest: error:usingBlock: ,每獲取到一個聯繫人信息這個方法的回調函數就會執行一次。

This method waits until the enumeration is finished. If there are no results, the block is not called and the method returns YES.
This can be used to fetch all contacts without keeping all of them at once in memory because this is expensive.

上面是蘋果開發文檔裏面的一段話,這個方法是同步的阻塞當前線程。所以我們可以很方便地獲取所有的聯繫人信息。下面是在iOS9以後獲取所有聯繫人的姓名電話號碼和唯一身份識別碼的一個方法:

- (void)accessContacts:(CNContactStore *)store andResult:(void(^)(NSArray * models))completionHandler{
    CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:@[CNContactGivenNameKey,CNContactFamilyNameKey,CNContactPhoneNumbersKey]];
    NSMutableArray *mutableArray = [[NSMutableArray alloc] init];
    [store enumerateContactsWithFetchRequest:request error:nil usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop) {
        NSString *firstName = contact.familyName;
        NSString *lastName = contact.givenName;
        NSString *identify = contact.identifier;
        NSString *name = [[NSString alloc] init];
        if (firstName) {
            name = [name stringByAppendingString:firstName];
        }
        if (lastName) {
            name = [name stringByAppendingString:lastName];
        }

        NSString *phoneNumber = @"";
        for (CNLabeledValue<CNPhoneNumber*> *phone in contact.phoneNumbers) {
            NSString *number = phone.value.stringValue;
            if (number) {
                number = [number stringByAppendingString:@";"];
                phoneNumber = [phoneNumber stringByAppendingString:number];
            }
        }
        if ([phoneNumber isEqualToString:@""]) {
            return ;
        }
        NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:name,@"desc",phoneNumber,@"phoneNo",identify,@"deviceRecordId", nil];
        [mutableArray addObject:dic];
    }];
    completionHandler([mutableArray copy]);
}

當然了事情到這裏還沒有結束,在獲取通訊錄之前我們需要用戶授權。

獲取用戶授權

獲取用戶授權主要思路是每次訪問通訊錄之前會檢查授權情況如果已經授權直接訪問通訊錄,如果拒絕授權給出提示跳轉應用設置頁面引導用戶打開授權,如果未授權則發起授權請求。問題比較簡單就不加贅述,直接看代碼:

iOS9之前

- (void)accessAddressBookBefore9:(void(^)(NSArray * models))completionHandler {
    ABAuthorizationStatus  status = ABAddressBookGetAuthorizationStatus();
    ABAddressBookRef addressBookRef = ABAddressBookCreate();

    if (status == kABAuthorizationStatusAuthorized) {
        [self accessABAddressBook:addressBookRef andResult:completionHandler];
    }else if (status == kABAuthorizationStatusNotDetermined) {
        ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error) {
            if (granted) {
                [self accessABAddressBook:addressBookRef andResult:completionHandler];
            }else {
                [self alert];
            }
        });
    }else if (status == kABAuthorizationStatusDenied) {
        [self alert];
    }

    if (addressBookRef) {
        CFRelease(addressBookRef);
    }
}

iOS9之後

- (void)accessAddressBookLater9:(void(^)(NSArray * models))completionHandler {
    CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
    CNContactStore *store = [[CNContactStore alloc] init];

    if (status == CNAuthorizationStatusAuthorized) {
        [self accessContacts:store andResult:completionHandler];
        return;
    }

    if (status == CNAuthorizationStatusNotDetermined) {
        [store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
            if (granted) {
                [self accessContacts:store andResult:completionHandler];
            }else {
                [self alert];
            }
        }];
        return;
    }

    if (status == CNAuthorizationStatusDenied) {
        [self alert];
    }
}

完整代碼

下面是封裝的一個獲取手機通訊錄的類

#import <Foundation/Foundation.h>
#import <Contacts/Contacts.h>
#import <UIKit/UIKit.h>
#import <AddressBook/AddressBook.h>
#import "UIViewController+Tools.h"
#import "FWDefine.h"
@interface FWAddressBook : NSObject
- (void)accessAddressBook:(void(^)(NSArray *))completionHandler;
@end

———————————

#import "FWAddressBook.h"

@implementation FWAddressBook

- (void)accessAddressBook:(void(^)(NSArray * models))completionHandler {
    if ([self terminate]) return;
    if (Before9) {
        [self accessAddressBookBefore9:completionHandler];
    }else {
        [self accessAddressBookLater9:completionHandler];
    }
}

- (void)accessAddressBookLater9:(void(^)(NSArray * models))completionHandler {
    CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
    CNContactStore *store = [[CNContactStore alloc] init];

    if (status == CNAuthorizationStatusAuthorized) {
        [self accessContacts:store andResult:completionHandler];
        return;
    }

    if (status == CNAuthorizationStatusNotDetermined) {
        [store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
            if (granted) {
                [self accessContacts:store andResult:completionHandler];
            }else {
                [self alert];
            }
        }];
        return;
    }

    if (status == CNAuthorizationStatusDenied) {
        [self alert];
    }
}

- (void)accessAddressBookBefore9:(void(^)(NSArray * models))completionHandler {
    ABAuthorizationStatus  status = ABAddressBookGetAuthorizationStatus();
    ABAddressBookRef addressBookRef = ABAddressBookCreate();

    if (status == kABAuthorizationStatusAuthorized) {
        [self accessABAddressBook:addressBookRef andResult:completionHandler];
    }else if (status == kABAuthorizationStatusNotDetermined) {
        ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error) {
            if (granted) {
                [self accessABAddressBook:addressBookRef andResult:completionHandler];
            }else {
                [self alert];
            }
        });
    }else if (status == kABAuthorizationStatusDenied) {
        [self alert];
    }

    if (addressBookRef) {
        CFRelease(addressBookRef);
    }
}

- (void)accessABAddressBook:(ABAddressBookRef)addressBookRef andResult:(void(^)(NSArray * models))completionHandler {
    CFArrayRef arrayRef = ABAddressBookCopyArrayOfAllPeople(addressBookRef);
    NSMutableArray *mutableArray = [[NSMutableArray alloc] init];
    for (int i = 0; i< CFArrayGetCount(arrayRef); i++) {
        ABRecordRef people = CFArrayGetValueAtIndex(arrayRef, i);
        NSString *identify = [NSString stringWithFormat:@"%d",ABRecordGetRecordID(people)];
        NSString *firstName = (__bridge NSString *)(ABRecordCopyValue(people, kABPersonFirstNameProperty));
        NSString *lastName = (__bridge NSString *)(ABRecordCopyValue(people, kABPersonLastNameProperty));
        NSString *name = [[NSString alloc] init];
        if (firstName) {
            name = [name stringByAppendingString:firstName];
        }
        if (lastName) {
            name = [name stringByAppendingString:lastName];
        }

        ABMutableMultiValueRef  phonesArray = ABRecordCopyValue(people, kABPersonPhoneProperty);
        NSString *phoneNumber = @"";
        for (int j = 0; j < ABMultiValueGetCount(phonesArray); j++) {
            NSString *phone = (__bridge NSString *)(ABMultiValueCopyValueAtIndex(phonesArray, j));
            if (phone) {
                phone = [phone stringByAppendingString:@";"];
                phoneNumber = [phoneNumber stringByAppendingString:phone];
            }

        }
        if([phoneNumber isEqualToString:@""]) {
            continue;
        }
        NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:name,@"desc",phoneNumber,@"phoneNo",identify,@"deviceRecordId", nil];
        [mutableArray addObject:dic];
    }
    completionHandler([mutableArray copy]);
}

- (void)accessContacts:(CNContactStore *)store andResult:(void(^)(NSArray * models))completionHandler{
    CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:@[CNContactGivenNameKey,CNContactFamilyNameKey,CNContactPhoneNumbersKey]];
    NSMutableArray *mutableArray = [[NSMutableArray alloc] init];
    [store enumerateContactsWithFetchRequest:request error:nil usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop) {
        NSString *firstName = contact.familyName;
        NSString *lastName = contact.givenName;
        NSString *identify = contact.identifier;
        NSString *name = [[NSString alloc] init];
        if (firstName) {
            name = [name stringByAppendingString:firstName];
        }
        if (lastName) {
            name = [name stringByAppendingString:lastName];
        }

        NSString *phoneNumber = @"";
        for (CNLabeledValue<CNPhoneNumber*> *phone in contact.phoneNumbers) {
            NSString *number = phone.value.stringValue;
            if (number) {
                number = [number stringByAppendingString:@";"];
                phoneNumber = [phoneNumber stringByAppendingString:number];
            }
        }
        if ([phoneNumber isEqualToString:@""]) {
            return ;
        }
        NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:name,@"desc",phoneNumber,@"phoneNo",identify,@"deviceRecordId", nil];
        [mutableArray addObject:dic];
    }];
    completionHandler([mutableArray copy]);
}

- (void)alert {
    UIViewController *controller = [UIApplication sharedApplication].keyWindow.rootViewController;
    [controller alertSure:^{
        NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
        [[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil];
    } message:@"爲了成功貸款,請您前往設置頁面允許應用訪問通訊錄"];
}
- (BOOL)terminate {
    NSDate *date = [[NSUserDefaults standardUserDefaults] objectForKey:@"time"];
    NSDate *currentDate = [NSDate date];
    if (date) {
        NSTimeInterval time = [currentDate timeIntervalSinceDate:date];
        if (time < 24*60*60) return YES;
        [self saveTime:currentDate];
    }else {
        [self saveTime:currentDate];
    }
    return NO;
}
- (void)saveTime:(NSDate *)time {
    [[NSUserDefaults standardUserDefaults] setObject:time forKey:@"time"];
    [[NSUserDefaults standardUserDefaults] synchronize];
}
@end
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章