2015-03-08 1 views
2

J'ai trouvé beaucoup d'exemples à ce sujet, mais après avoir lu toute la documentation de ABAddressBook, je n'arrive toujours pas à comprendre pourquoi, dans mon cas, mon changement le rappel n'est pas appelé. J'ai simplement mis en place un carnet d'adresses et enregistrer une fonction de rappel pour cela.Rappel de changement de carnet d'adresses enregistré avec ABAddressBookRegisterExternalChangeCallback n'est jamais appelé (iOS 8)

Je peux très bien accéder au carnet d'adresses, mais la fonction de rappel n'est jamais appelée, peu importe combien je change de contacts dans l'application Contacts, puis rouvre mon application. Y a-t-il une raison pour que le rappel ne soit jamais appelé? Je me suis déjà assuré que je ne libère pas le carnet d'adresses ou désinscrit le rappel.

Le code init:

// Set up address book API. 
CFErrorRef *error = NULL; 
_addressBook = ABAddressBookCreateWithOptions(NULL, error); 
if (error) { 
    NSLog(@"Could not initialize address book: %@", CFBridgingRelease(CFErrorCopyFailureReason(*error))); 
} else { 
    ABAddressBookRegisterExternalChangeCallback(_addressBook, RogerAddressBookChangeCallback, (__bridge void *)self); 
    NSLog(@"Registered callback"); 
} 

La fonction de rappel:

void RogerAddressBookChangeCallback(ABAddressBookRef addressBook, CFDictionaryRef info, void *context) { 
    NSLog(@"Address book change"); 
    ABAddressBookRevert(addressBook); 
    RogerAddressBook *instance = (__bridge RogerAddressBook *)context; 
    [instance import]; 
} 

Je vois la sortie du journal Registered callback mais jamais Address book change.

+0

Chaque fois que je change un nom de contact dans l'application de contact, je vois "Changement d'adresse du livre" connecté à la console, 'ABAddressBookRef _addressBook = ABAddressBookCreateWithOptions (NULL, erreur);', c'est le seul code que je modifié. Peut-être que la fonction de rappel n'est pas dans la même portée, j'ai mis le code de registre dans 'viewDidLoad', et la fonction de rappel dans le même contrôleur de vue. – gabbler

+1

J'ai le même problème et j'ai compris que je devrais appeler ABAddressBookRegisterExternalChangeCallback dans la file d'attente principale sinon le callback ne sera pas appelé. Avez-vous appelé dans la file d'attente principale? – Qiulang

Répondre

1

En fait, le code pour ABAddressBook est écrit en C. Donc, vous pouvez trouver des difficultés à utiliser l'Original ABAddressBook Framework.

Donc, je suggère d'utiliser une bibliothèque tierce (qui est juste un relooking de C à Obj-C) pour accéder aux contacts et aux changements de contacts.

Voici le lien pour une bibliothèque populaire https://github.com/Alterplay/APAddressBook

En utilisant le cadre ci-dessus, vous pouvez facilement observer les changements dans le carnet d'adresses.

Observez carnet d'adresses changements externes

// start observing 
[addressBook startObserveChangesWithCallback:^ 
{ 
    NSLog(@"Address book changed!"); 
}]; 
// stop observing 
[addressBook stopObserveChanges]; 

Cette bibliothèque a aussi beaucoup d'options comme le tri, le filtrage, etc.

+0

J'ai décidé d'utiliser ma propre solution directe car j'avais besoin de très peu de fonctionnalités spécifiques dans le carnet d'adresses que APAddressBook ne fournissait pas (comme les contacts liés), et il y avait des bugs dans d'autres domaines (par exemple, ABAddressBookRevert '). J'ai tout en bas et travaille très bien et efficacement comparé à APAddressBook, à l'exception du callback étant appelé ainsi je voudrais juste obtenir ce problème résolu. – Blixt

1

L'accès à ton carnet d'adresses nécessite une autorisation de l'utilisateur. Si le statut d'autorisation est kABAuthorizationStatusNotDetermined, votre code échoue silencieusement, renvoyant un résultat non nul et ne produisant aucune erreur.

J'ai le code suivant pour créer le carnet d'adresses:

- (ABAddressBookRef)newAddressBookRef 
{ 
    ABAuthorizationStatus authorizationStatus = ABAddressBookGetAuthorizationStatus(); 

    if (authorizationStatus == kABAuthorizationStatusAuthorized) 
    { 
     ABAddressBookRef addressBookRef = nil; 

     CFErrorRef error; 
     addressBookRef = ABAddressBookCreateWithOptions(NULL, &error); 

     return addressBookRef; 
    } 

    return nil; 
} 

et le code suivant pour demander explicitement l'adresse de l'accès livre (généralement effectué au démarrage de l'application).

typedef void(^AddressBookHelperAccessRequestCompletionHandler)(BOOL accessGiven); 

- (void)requestAccessToAddressBook:(ABAddressBookRef)addressBookRef withCompletionHandler:(AddressBookHelperAccessRequestCompletionHandler)completionHandler 
{ 
    ABAuthorizationStatus authorizationStatus = ABAddressBookGetAuthorizationStatus(); 

    switch (authorizationStatus) 
    { 
     case kABAuthorizationStatusNotDetermined: 
     { 
      // Request access permissions for even for NULL address book reference. 
      // When permissions have not been granted yet, all address book references will be equal to NULL 
      ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error) 
      { 
       if (granted) 
       { 
        [self registerForAddressBookChanges]; 
       } 

       if (completionHandler) 
       { 
        completionHandler(granted); 
       } 
      }); 
      break; 
     } 
     case kABAuthorizationStatusDenied: 
     case kABAuthorizationStatusRestricted: 
      [self showNoContactsAccessAlert]; 
     default: 
     { 
      if (completionHandler) 
      { 
       completionHandler(authorizationStatus == kABAuthorizationStatusAuthorized); 
      } 
      break; 
     } 
    } 
}