2012-09-20 4 views
14

Meine Methode zum programmgesteuerten Abrufen von E-Mail-Adressen aus dem Adressbuch scheint nicht mehr auf iOS 6-Geräten zu funktionieren. Es funktionierte in iOS 5 und funktioniert seltsamerweise immer noch im iOS 6 Simulator. Gibt es eine neue Möglichkeit zum programmgesteuerten Abrufen von Kontakten aus dem Adressbuch eines Benutzers?iOS 6 Adressbuch funktioniert nicht?

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

Um zu verdeutlichen, stürzt das oben genannte nicht ab, es gibt einfach keine Ergebnisse zurück. ABAddressBookCopyArrayOfAllPeople ist leer. Vielen Dank!

Antwort

12

Wahrscheinlich im Zusammenhang mit den neuen Datenschutzeinstellungen-wie von iOS 6, auf dem Gerät, eine App kann nicht auf die Kontakte des Benutzers ohne ihre Erlaubnis zugreifen. Aus der Dokumentation:

auf iOS 6.0 und höher, wenn der Anrufer keinen Zugriff auf die Adressbuch-Datenbank hat:

• Für Anwendungen verknüpfen gegen iOS 6.0 und höher, gibt diese Funktion NULL zurück.

• Für Anwendungen, die mit einer früheren Version von iOS verknüpft sind, gibt diese Funktion eine leere schreibgeschützte Datenbank zurück.

Wenn Sie nicht die Berechtigungen gesehen Alarm kommen („SomeApp würde Zugriff auf Ihre Kontakte gefallen“), ist es möglich, dass die direkte Adressbuchs APIs einfach davon ausgehen, dass sie keinen Zugang hat und unbemerkt fehlschlagen ; Sie müssen möglicherweise etwas aus dem AddressBookUI-Framework anzeigen, um es auszulösen.

+2

Ja, du hast Recht. Brauchen Sie ABAddressBookRequestAccessWithCompletion(). Wie kann ich überprüfen, ob diese Methode existiert (für Keller

52

Ich habe eine Hilfsklasse, AddressBookHelper, erstellt, um Abwärtskompatibilität zu behandeln. Hier sind die Eingeweide:

-(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

Aktualisiert: einige fehlende 'CFRelease hinzugefügt 'ruft auf um zu verhindern, dass' AddressBook' in diesen Code eindringt. –

+0

Hallo, frage mich nur, warum der Aufruf von dispatch_async()? Ich habe es ohne es versucht und es funktioniert perfekt und blockiert auch nicht meine UI, während das Adressbuch neu geladen wird. – jklp

+0

Die [Dokumentation] (http://developer.apple.com/library/ios/Documentation/AddressBook/Reference/ABAddressBookRef_iPhoneOS/Reference/reference.html#//apple_ref/doc/uid/TP40007099-CH200-SW17) besagt, dass 'Der Completion-Handler wird für eine beliebige Warteschlange aufgerufen. Wenn Ihre App ein Adressbuch in der gesamten App verwendet, müssen Sie dafür sorgen, dass die gesamte Verwendung dieses Adressbuchs in einer einzigen Warteschlange ausgeführt wird, um den korrekten thread-sicheren Betrieb zu gewährleisten. Beim Testen kam es zu einigen Abstürzen (kann nicht abgerufen werden die Details), die Threadsicherheitsprobleme vorschlugen, die mich zu den Dokumenten führten. –

12

Versuchen mit diesem: Zugriff auf das Adressbuch muss gewährt werden, bevor es Zugang programmatisch sein kann. Hier ist, was ich getan habe.

#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

Wahrscheinlich auf die neuen Datenschutzkontrollen im Zusammenhang, wie von iOS 6, auf dem Gerät kann eine App nicht die Kontakte des Benutzers, ohne ihre Erlaubnis zugreifen.

Code:

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