¿La libreta de direcciones de iOS 6 no funciona?

Mi método de recuperar mediante progtwigción las direcciones de correo electrónico de la Libreta de direcciones ya no parece funcionar en dispositivos con iOS 6. Funcionó en iOS 5 y, curiosamente, sigue funcionando en iOS 6 Simulator. ¿Hay una nueva forma de recuperar contactos desde la Libreta de direcciones de un usuario mediante progtwigción?

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]; } 

Para aclarar, lo anterior no falla, simplemente no devuelve resultados. ABAddressBookCopyArrayOfAllPeople está vacío. ¡Gracias!

Probablemente relacionado con los nuevos controles de privacidad: a partir de iOS 6, en el dispositivo, una aplicación no puede acceder a los contactos del usuario sin su permiso. De la documentation:

En iOS 6.0 y posterior, si la persona que llama no tiene acceso a la database de la libreta de direcciones:

• Para aplicaciones vinculadas a iOS 6.0 y posteriores, esta function devuelve NULL.

• Para las aplicaciones vinculadas a versiones anteriores de iOS, esta function devuelve una database vacía de solo lectura.

Si no ha visto aparecer la alerta de permissions ("A SomeApp le gustaría tener acceso a sus contactos"), es posible que las API directas de la libreta de direcciones simplemente asumn que no tienen acceso y fallan silenciosamente; es posible que tenga que mostrar algo del marco de la dirección de dirección de correo electrónico para activarlo.

Creé una class auxiliar, AddressBookHelper , para manejar la compatibilidad con versiones anteriores. Estas son las agallas:

 -(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]; }; 

Intente con esto: se debe otorgar acceso a la libreta de direcciones antes de que se pueda acceder mediante progtwigción. Esto es lo que terminé haciendo.

  #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 } 

Probablemente relacionado con los nuevos controles de privacidad, a partir de iOS 6, en el dispositivo, una aplicación no puede acceder a los contactos del usuario sin su permiso.

Código:

 -(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); }