Je veux obtenir une liste de tous les contacts d'un iPhone.
J'ai vérifié Address Book
référence, je risque de manquer quelque chose mais je ne savais pas c'est une méthode qui permet d'obtenir une liste de contacts.
Je veux obtenir une liste de tous les contacts d'un iPhone.
J'ai vérifié Address Book
référence, je risque de manquer quelque chose mais je ne savais pas c'est une méthode qui permet d'obtenir une liste de contacts.
Un couple de réactions non seulement à votre question, mais aussi beaucoup de réponses fournies ici (qui ne demande pas la permission, ne pas manipuler ABAddressBookCreateWithOptions
correctement les erreurs, ou de fuite):
Tout d'abord, assurez-vous que vous avez correctement la demande d'autorisation pour l'application à accéder à vos contacts. Par exemple:
ABAuthorizationStatus status = ABAddressBookGetAuthorizationStatus();
if (status == kABAuthorizationStatusDenied) {
// if you got here, user had previously denied/revoked permission for your
// app to access the contacts, and all you can do is handle this gracefully,
// perhaps telling the user that they have to go to settings to grant access
// to contacts
[[[UIAlertView alloc] initWithTitle:nil message:@"This app requires access to your contacts to function properly. Please visit to the \"Privacy\" section in the iPhone Settings app." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show];
return;
}
CFErrorRef error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
if (error) {
NSLog(@"ABAddressBookCreateWithOptions error: %@", CFBridgingRelease(error));
if (addressBook) CFRelease(addressBook);
return;
}
if (status == kABAuthorizationStatusNotDetermined) {
// present the user the UI that requests permission to contacts ...
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
if (error) {
NSLog(@"ABAddressBookRequestAccessWithCompletion error: %@", CFBridgingRelease(error));
}
if (granted) {
// if they gave you permission, then just carry on
[self listPeopleInAddressBook:addressBook];
} else {
// however, if they didn't give you permission, handle it gracefully, for example...
dispatch_async(dispatch_get_main_queue(), ^{
// BTW, this is not on the main thread, so dispatch UI updates back to the main queue
[[[UIAlertView alloc] initWithTitle:nil message:@"This app requires access to your contacts to function properly. Please visit to the \"Privacy\" section in the iPhone Settings app." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show];
});
}
if (addressBook) CFRelease(addressBook);
});
} else if (status == kABAuthorizationStatusAuthorized) {
[self listPeopleInAddressBook:addressBook];
if (addressBook) CFRelease(addressBook);
}
Remarque que ci-dessus, je n'ai pas utilisé le modèle suggéré par d'autres:
CFErrorRef *error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
Ce n'est pas correct. Comme vous pourrez le voir ci-dessus, vous souhaitez:
CFErrorRef error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
C'est le modèle qu'Apple utilise, et, plus important encore, l'ancien ne sera pas capturer l'erreur correctement, alors que ce dernier. Aussi, assurez-vous de vérifier pour voir si error
a NULL
, et si non, traiter l'erreur, mais alors CFRelease
le error
(ou de transférer la propriété à l'ARC comme je l'ai fait), sinon vous allez fuite de cet objet.
Pour itérer sur les contacts, vous souhaitez:
- (void)listPeopleInAddressBook:(ABAddressBookRef)addressBook
{
NSInteger numberOfPeople = ABAddressBookGetPersonCount(addressBook);
NSArray *allPeople = CFBridgingRelease(ABAddressBookCopyArrayOfAllPeople(addressBook));
for (NSInteger i = 0; i < numberOfPeople; i++) {
ABRecordRef person = (__bridge ABRecordRef)allPeople[i];
NSString *firstName = CFBridgingRelease(ABRecordCopyValue(person, kABPersonFirstNameProperty));
NSString *lastName = CFBridgingRelease(ABRecordCopyValue(person, kABPersonLastNameProperty));
NSLog(@"Name:%@ %@", firstName, lastName);
ABMultiValueRef phoneNumbers = ABRecordCopyValue(person, kABPersonPhoneProperty);
CFIndex numberOfPhoneNumbers = ABMultiValueGetCount(phoneNumbers);
for (CFIndex i = 0; i < numberOfPhoneNumbers; i++) {
NSString *phoneNumber = CFBridgingRelease(ABMultiValueCopyValueAtIndex(phoneNumbers, i));
NSLog(@" phone:%@", phoneNumber);
}
CFRelease(phoneNumbers);
NSLog(@"=============================================");
}
}
Je tiens à attirer votre attention sur une clé assez en détail, à savoir le "Créer une Règle":
Fondement de base fonctions ont des noms qui indiquent quand vous êtes propriétaire d'un objet retourné:
Création de l'objet des fonctions qui ont "
Create
" ancrée dans le nom;Objet-la duplication des fonctions qui ont "
Copy
" ancrée dans le nom.Si vous êtes propriétaire d'un objet, il est de votre responsabilité de renoncer à la propriété (à l'aide de CFRelease) lorsque vous avez terminé avec elle.
Cela signifie que vous assumer la responsabilité de vous libérer de tout objet retourné par un Fondement de Base de la fonction avec des Create
ou Copy
dans le nom. Vous pouvez soit téléphoner CFRelease
explicitement (comme je l'ai fait ci-dessus avec addressBook
, allPeople
, et phoneNumbers
) ou, pour les objets qui prennent en charge sans frais de transition, vous pouvez transférer la propriété à l'ARC avec __bridge_transfer
ou CFBridgingRelease
(comme je l'ai fait ci-dessus avec lastName
, firstName
, et phoneNumber
).
L'analyseur statique (appuyez sur maj+commande+B dans Xcode, ou choisissez "Analyse" du "Produit" menu) permet d'identifier de nombreuses situations dans lesquelles vous avez négligé d'observer cette "Créer une Règle" et n'a pas pu libérer les objets appropriés. Donc, chaque fois que l'écriture de Base de la Fondation de ce code, toujours exécuter par le biais de l'analyseur statique assurez-vous que vous n'avez pas de fuites apparentes.
Peut - ABPerson
fonction ABAddressBookCopyArrayOfAllPeople pourraient faire?
ABAddressBookRef addressBook = ABAddressBookCreate( );
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople( addressBook );
CFIndex nPeople = ABAddressBookGetPersonCount( addressBook );
for ( int i = 0; i < nPeople; i++ )
{
ABRecordRef ref = CFArrayGetValueAtIndex( allPeople, i );
...
}
Utilisez ce code pour afficher tous les noms + lastnames + phonenumbers (iOS 6). Fonctionne sur simulateur de trop:
CFErrorRef *error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex numberOfPeople = ABAddressBookGetPersonCount(addressBook);
for(int i = 0; i < numberOfPeople; i++) {
ABRecordRef person = CFArrayGetValueAtIndex( allPeople, i );
NSString *firstName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonFirstNameProperty));
NSString *lastName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonLastNameProperty));
NSLog(@"Name:%@ %@", firstName, lastName);
ABMultiValueRef phoneNumbers = ABRecordCopyValue(person, kABPersonPhoneProperty);
for (CFIndex i = 0; i < ABMultiValueGetCount(phoneNumbers); i++) {
NSString *phoneNumber = (__bridge_transfer NSString *) ABMultiValueCopyValueAtIndex(phoneNumbers, i);
NSLog(@"phone:%@", phoneNumber);
}
NSLog(@"=============================================");
}
Dans iOS 6, assurez-vous d'utiliser ABAddressBookCreateWithOptions
, qui est la version mise à jour de ABAddressBookCreate
CFErrorRef * error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex numberOfPeople = ABAddressBookGetPersonCount(addressBook);
for(int i = 0; i < numberOfPeople; i++){
ABRecordRef person = CFArrayGetValueAtIndex( allPeople, i );
// More code here
}
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.