Адресная книга iOS 6 не работает?
Мой метод программного получения адресов электронной почты из адресной книги больше не работает на устройствах iOS 6. Он работал в iOS 5 и странно, все еще работает в iOS 6 Simulator. Есть ли новый способ программного извлечения контактов из адресной книги пользователей?
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 пуст. Спасибо!
Ответы
Ответ 1
Вероятно, связанный с новыми элементами управления конфиденциальности - с iOS 6, на устройстве, приложение не может обращаться к контактам пользователей без их разрешения. Из документации:
В iOS 6.0 и более поздних версиях, если вызывающий абонент не имеет доступа к База данных адресной книги:
• Для приложений, связанных с iOS 6.0 и более поздними версиями, эта функция возвращает NULL.
• Для приложений, связанных с предыдущей версией iOS, эта функция возвращает пустую базу данных только для чтения.
Если вы не заметили, что появилось предупреждение о разрешении ( "SomeApp хочет получить доступ к вашим контактам" ), возможно, что API-интерфейсы прямой адресной книги просто предполагают, что они не имеют доступа и молчат; вам может потребоваться отобразить что-то из структуры AddressBookUI, чтобы вызвать его.
Ответ 2
Я создал вспомогательный класс 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];
};
Ответ 3
Попробуйте следующее:
доступ к адресной книге должен быть предоставлен, прежде чем он сможет получить доступ программно. Вот что я сделал.
#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
}
Ответ 4
Вероятно, связанный с новыми элементами управления конфиденциальности, с 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);
}