2012-09-20 128 views
14

我從地址簿中以編程方式檢索電子郵件地址的方法似乎不再適用於iOS 6設備。它在iOS 5中工作,奇怪的是,仍然在iOS 6模擬器中工作。有沒有新的方式來編程檢索用戶的地址簿中的聯繫人?iOS 6地址簿無法使用?

ABAddressBookRef addressBook = ABAddressBookCreate(); 
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook); 
CFIndex nPeople = ABAddressBookGetPersonCount(addressBook); 

self.contacts = [[NSMutableArray alloc] init]; 

int contactIndex = 0; 
for (int i = 0; i < nPeople; i++) { 
    // Get the next address book record. 
    ABRecordRef record = CFArrayGetValueAtIndex(allPeople, i);   

    // Get array of email addresses from address book record. 
    ABMultiValueRef emailMultiValue = ABRecordCopyValue(record, kABPersonEmailProperty); 
    NSArray *emailArray = (__bridge_transfer NSArray *)ABMultiValueCopyArrayOfAllValues(emailMultiValue); 

    [self.contacts addObject:emailArray]; 
} 

澄清,上述不會崩潰,它只是返回沒有結果。 ABAddressBookCopyArrayOfAllPeople爲空。謝謝!

回答

12

可能與設備上的新隱私控制相關 - 從iOS 6開始,應用程序無法在未經他們許可的情況下訪問用戶的聯繫人。從文檔:

在iOS 6.0及更高版本,如果主叫方沒有訪問 通訊錄數據庫:

•對於反對的iOS 6.0或更高版本的關聯應用,該函數返回NULL。

•對於與先前版本的iOS鏈接的應用程序,此函數返回一個空的只讀數據庫。

如果您還沒有看到權限警告上來(「SomeApp想訪問你的通訊錄」),它可能是直接的地址簿的API只是認爲他們沒有獲得和靜默失敗;你可能不得不從AddressBookUI框架中顯示一些東西來觸發它。

+2

是的,你說得對。需要使用ABAddressBookRequestAccessWithCompletion()。我如何檢查此方法是否存在(對於 Keller

52

我創建了一個幫助器類AddressBookHelper來處理向後兼容性。這裏有膽量:

-(BOOL)isABAddressBookCreateWithOptionsAvailable { 
    return &ABAddressBookCreateWithOptions != NULL; 
} 

-(void)loadContacts { 
    ABAddressBookRef addressBook; 
    if ([self isABAddressBookCreateWithOptionsAvailable]) { 
     CFErrorRef error = nil; 
     addressBook = ABAddressBookCreateWithOptions(NULL,&error); 
     ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) { 
      // callback can occur in background, address book must be accessed on thread it was created on 
      dispatch_async(dispatch_get_main_queue(), ^{ 
       if (error) { 
        [self.delegate addressBookHelperError:self]; 
       } else if (!granted) { 
        [self.delegate addressBookHelperDeniedAcess:self]; 
       } else { 
        // access granted 
        AddressBookUpdated(addressBook, nil, self); 
        CFRelease(addressBook); 
       } 
      }); 
     }); 
    } else { 
     // iOS 4/5 
     addressBook = ABAddressBookCreate(); 
     AddressBookUpdated(addressBook, NULL, self); 
     CFRelease(addressBook); 
    } 
} 

void AddressBookUpdated(ABAddressBookRef addressBook, CFDictionaryRef info, void *context) { 
    AddressBookHelper *helper = (AddressBookHelper *)context; 
    ABAddressBookRevert(addressBook); 
    CFArrayRef people = ABAddressBookCopyArrayOfAllPeople(addressBook); 

    // process the contacts to return 
    NSArray *contacts = ...  

    [[helper delegate] addressBookHelper:helper finishedLoading:contacts]; 
}; 
+0

更新:增加了一些缺失的'CFRelease在這段代碼中調用''防止泄漏'AddressBook'。 –

+0

嗨,只是想知道爲什麼調用dispatch_async()?我試過沒有它,它完美的作品,也不會阻止我的用戶界面,而地址簿正在重新加載。 – jklp

+0

[documentation](http://developer.apple.com/library/ios/Documentation/AddressBook/Reference/ABAddressBookRef_iPhoneOS/Reference/reference.html#//apple_ref/doc/uid/TP40007099-CH200-SW17)聲明: '完成處理程序在任意隊列上調用。如果您的應用程序在整個應用程序中使用通訊簿,則您有責任確保將該通訊錄的所有用法分派到單個隊列中,以確保正確的線程安全操作。「在測試中,我遇到了一些崩潰(無法記憶細節),這表明線程安全問題,這導致我的文檔。 –

12

嘗試這樣的: 訪問地址簿必須被授予之前,它可以訪問編程。這是我最終做的。

#import <AddressBookUI/AddressBookUI.h> 

    // Request authorization to Address Book 
    ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, NULL); 

    if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined) { 
    ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error) { 
     // First time access has been granted, add the contact 
     [self _addContactToAddressBook]; 
    }); 
    } 
    else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized) { 
    // The user has previously given access, add the contact 
    [self _addContactToAddressBook]; 
    } 
    else { 
    // The user has previously denied access 
    // Send an alert telling user to change privacy setting in settings app 
    } 
0

可能與iOS 6以上的新隱私控制有關,在設備上,應用程序無法在未經他們許可的情況下訪問用戶的聯繫人。

代碼:

-(void)addressBookValidation 
{ 



NSUserDefaults *prefs=[NSUserDefaults standardUserDefaults]; 
ABAddressBookRef addressbook = ABAddressBookCreate(); 
__block BOOL accessGranted = NO; 

if (ABAddressBookRequestAccessWithCompletion != NULL) 
{ 
    if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined) 
    { 
     dispatch_semaphore_t sema = dispatch_semaphore_create(0); 
     ABAddressBookRequestAccessWithCompletion(addressbook, ^(bool granted, CFErrorRef error) 
               { 
                accessGranted = granted; 
                dispatch_semaphore_signal(sema); 
               }); 
     dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); 
     dispatch_release(sema); 
    } 
    else if(ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized) 
    { 
     accessGranted = YES; 
    } 
    else if (ABAddressBookGetAuthorizationStatus()==kABAuthorizationStatusDenied) 
    { 
     accessGranted = NO; 
    } 
    else if (ABAddressBookGetAuthorizationStatus()==kABAuthorizationStatusRestricted){ 
     accessGranted = NO; 
    } 
    else 
    { 
     accessGranted = YES; 
    } 


} 
else 
{ 
    accessGranted = YES; 
} 
[prefs setBool:accessGranted forKey:@"addressBook"]; 

NSLog(@"[prefs boolForKey:@'addressBook']--->%d",[prefs boolForKey:@"addressBook"]); 
[prefs synchronize]; 
CFRelease(addressbook); 
}