如何获取iOS 6中用户联系人的列表?

时间:2012-11-09 20:56:47

标签: iphone ios xcode cocoa-touch ios6

我已经使用以下代码几年了,而且它一直有效,但看起来像iOS 6它已不再存在了。如何获取iOS 6设备上所有联系人的列表?

ABAddressBookRef myAddressBook = ABAddressBookCreate();
        NSMutableArray *people = (__bridge_transfer NSMutableArray *)ABAddressBookCopyArrayOfAllPeople(myAddressBook);
        CFRelease(myAddressBook);

        // repeat through all contacts in the inital array we loaded
        for(int i=0; i<[people count]; i++)
        {
            NSString *aName;
            NSString *firstName = (__bridge_transfer NSString *)ABRecordCopyValue((__bridge ABRecordRef)([people objectAtIndex:i]), kABPersonFirstNameProperty);
            NSString *lastName = (__bridge_transfer NSString *)ABRecordCopyValue((__bridge ABRecordRef)([people objectAtIndex:i]), kABPersonLastNameProperty);

            if (([firstName isEqualToString:@""] || [firstName isEqualToString:@"(null)"] || firstName == nil) &&
                ([lastName isEqualToString:@""] || [lastName isEqualToString:@"(null)"] || lastName == nil))
            {
                // do nothing
            }
            else 
            {
                aName = [NSString stringWithFormat:@"%@ %@", firstName, lastName];

                if ([firstName isEqualToString:@""] || [firstName isEqualToString:@"(null)"] || firstName == nil)
                {
                    aName = [NSString stringWithFormat:@"%@", lastName];
                }

                if ([lastName isEqualToString:@""] || [lastName isEqualToString:@"(null)"] || lastName == nil)
                {
                    aName = [NSString stringWithFormat:@"%@", firstName];
                }

                [self.tableItems addObject:aName];
            }

        }

        [self.tableItems sortUsingSelector:@selector(compare:)];

2 个答案:

答案 0 :(得分:4)

在ios6中,您需要请求阅读AddressBook的权限,否则您将获得nil。使用这样的东西:

- (BOOL)askContactsPermission {
    __block BOOL ret = NO;
    if (ABAddressBookRequestAccessWithCompletion != NULL) { // we're on iOS6

        dispatch_semaphore_t sema = dispatch_semaphore_create(0);
        ABAddressBookRef addressBook = ABAddressBookCreate();
        ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
            ret = granted;
            dispatch_semaphore_signal(sema);
        });
        if (addressBook) {
            CFRelease(addressBook);
        }

        dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
        dispatch_release(sema);
    }
    else { // we're on iOS5 or older
        ret = YES;
    }

    return ret;
}

如果此方法返回NO,运气不好,您将无法访问AB。我在这里使用信号量锁定,因为如果用户不允许AB,我不想继续使用我的应用程序。还有其他方法,只需检查API。

答案 1 :(得分:4)

您需要询问用户是否允许在您这样做时触发用户提示。这是使用执行块来处理结果的另一种方法,如果您需要从公共代码查询当前访问状态,也可以使用它与版本无关。

我实现了一个像这样的访问管理器

AppContactsAccessManager.h

#import <AddressBook/AddressBook.h>

typedef enum
{
    kABAuthStatusNotDetermined = 0,
    kABAuthStatusRestricted,
    kABAuthStatusDenied,
    kABAuthStatusAuthorized,
    kABAuthStatusPending,
}AddressBookAuthStatus;

typedef void (^AddressbookRequestHandler)(ABAddressBookRef addressBookRef, BOOL available);

@interface AppContactsAccessManager : NSObject
{
     AddressBookAuthStatus status;
}
- (void) requestAddressBookWithCompletionHandler:(AddressbookRequestHandler)handler;
- (AddressBookAuthStatus) addressBookAuthLevel;

@end

AppContactsAccessManager.m

@implementation AppContactsAccessManager

- (BOOL) isStatusAvailable:(AddressBookAuthStatus)theStatus
{
    return (theStatus == kABAuthStatusAuthorized || theStatus == kABAuthStatusRestricted);
}

- (void) requestAddressBookWithCompletionHandler:(AddressbookRequestHandler)handler
{
    ABAddressBookRef addressBookRef = NULL;

    if([self isiOS6]){
        addressBookRef = ABAddressBookCreateWithOptions(nil, nil);
        ABAuthorizationStatus curStatus = ABAddressBookGetAuthorizationStatus();
        if(curStatus == kABAuthorizationStatusNotDetermined)
        {
            status = kABAuthStatusPending;
            ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error) {
                status = ABAddressBookGetAuthorizationStatus();
                if(handler != NULL){
                    handler(addressBookRef, [self isStatusAvailable:status]);
                }
            });
        }else
        {
            status = curStatus;
            dispatch_async(dispatch_get_current_queue(), ^{
                if(handler != NULL){
                    handler(addressBookRef, [self isStatusAvailable:status]);
                }
            });
        }
    }else
    {
        addressBookRef = ABAddressBookCreate();
        status = kABAuthStatusAuthorized;
        dispatch_async(dispatch_get_current_queue(), ^{
            if(handler != NULL){
                handler(addressBookRef, [self isStatusAvailable:status]);
            }
            });
        }
}

- (AddressBookAuthStatus) addressBookAuthLevel
{
        return status;
}

@end

用法看起来像:

AppContactsAccessManager* accessMgr = [AppContactsAccessManager new];
[accessMgr requestAddressBookWithCompletionHandler:^(ABAddressBookRef theAddressBookRef, BOOL available) {
    // do your addressbook stuff in here
}];