sincronizar sesion recuperar porque mis los iniciar guarda contactos cantidad aparecen administrar ios ios4 abaddressbook

ios - sesion - recuperar contactos icloud iphone



Obtenga una lista de todos los contactos en iOS (13)

Quiero obtener una lista de todos los contactos de un iPhone.

Comprobé la referencia de la Address Book , es posible que haya omitido algo, pero no vi que proporcione un método para obtener una lista de contactos.


¿Quizás la función ABAddressBookCopyArrayOfAllPeople podría funcionar?

Example :

ABAddressBookRef addressBook = ABAddressBookCreate( ); CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople( addressBook ); CFIndex nPeople = ABAddressBookGetPersonCount( addressBook ); for ( int i = 0; i < nPeople; i++ ) { ABRecordRef ref = CFArrayGetValueAtIndex( allPeople, i ); ... }


Asegúrate de tener la importación correcta

#import <AddressBook/AddressBook.h>

Luego puede obtener un objeto CFArray con todos los contactos usando

CFArrayRef ABAddressBookCopyArrayOfAllPeople (ABAddressBookRef addressBook);



En iOS 6, asegúrese de utilizar ABAddressBookCreateWithOptions , que es la versión actualizada 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 }


En mi respuesta original, al final de esta respuesta, muestro cómo recuperar contactos en versiones de iOS anteriores a la 9.0 de una manera que aborda algunos de los problemas que implican otras respuestas aquí.

Pero, si solo es compatible con iOS 9 y posterior, uno debe usar el marco de Contacts , evitando algunos de los molestos problemas de conexión que conlleva cuando se utiliza el marco anterior de la AddressBook .

Entonces, en iOS 9, usarías el marco de Contacts :

@import Contacts;

También necesita actualizar su Info.plist , agregando un NSContactsUsageDescription para explicar por qué su aplicación requiere acceso a los contactos.

Y luego haz algo como lo siguiente:

CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts]; if (status == CNAuthorizationStatusDenied || status == CNAuthorizationStatusRestricted) { UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Access to contacts." message:@"This app requires access to contacts because ..." preferredStyle:UIAlertControllerStyleActionSheet]; [alert addAction:[UIAlertAction actionWithTitle:@"Go to Settings" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString] options:@{} completionHandler:nil]; }]]; [alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]]; [self presentViewController:alert animated:TRUE completion:nil]; return; } CNContactStore *store = [[CNContactStore alloc] init]; [store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) { // make sure the user granted us access if (!granted) { dispatch_async(dispatch_get_main_queue(), ^{ // user didn''t grant access; // so, again, tell user here why app needs permissions in order to do it''s job; // this is dispatched to the main queue because this request could be running on background thread }); return; } // build array of contacts NSMutableArray *contacts = [NSMutableArray array]; NSError *fetchError; CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:@[CNContactIdentifierKey, [CNContactFormatter descriptorForRequiredKeysForStyle:CNContactFormatterStyleFullName]]]; BOOL success = [store enumerateContactsWithFetchRequest:request error:&fetchError usingBlock:^(CNContact *contact, BOOL *stop) { [contacts addObject:contact]; }]; if (!success) { NSLog(@"error = %@", fetchError); } // you can now do something with the list of contacts, for example, to show the names CNContactFormatter *formatter = [[CNContactFormatter alloc] init]; for (CNContact *contact in contacts) { NSString *string = [formatter stringFromContact:contact]; NSLog(@"contact = %@", string); } }];

A continuación está mi respuesta aplicable si es compatible con las versiones de iOS anteriores a iOS 9.0.

-

Un par de reacciones no solo a su pregunta, sino también a muchas de las respuestas proporcionadas aquí (que no solicitan permiso, no manejan los errores ABAddressBookCreateWithOptions correctamente o tienen fugas):

  1. Obviamente, importe el marco AddressBook :

    #import <AddressBook/AddressBook.h>

    o

    @import AddressBook;

  2. Debe solicitar permiso para que la aplicación acceda a los contactos. Por ejemplo:

    ABAuthorizationStatus status = ABAddressBookGetAuthorizationStatus(); if (status == kABAuthorizationStatusDenied || status == kABAuthorizationStatusRestricted) { // 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 (!addressBook) { NSLog(@"ABAddressBookCreateWithOptions error: %@", CFBridgingRelease(error)); return; } 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]; }); } CFRelease(addressBook); });

  3. Tenga en cuenta que arriba, no he usado el patrón sugerido por otros:

    CFErrorRef *error = NULL; ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);

    Eso no es correcto. Como verá más arriba, quiere:

    CFErrorRef error = NULL; ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);

    El primer patrón no capturará el error correctamente, mientras que el último lo hará. Si el error no fue NULL , no se olvide de CFRelease (o transferir la propiedad a ARC como lo hice) o de lo contrario perderá ese objeto.

  4. Para iterar a través de los contactos, desea:

    - (void)listPeopleInAddressBook:(ABAddressBookRef)addressBook { NSArray *allPeople = CFBridgingRelease(ABAddressBookCopyArrayOfAllPeople(addressBook)); NSInteger numberOfPeople = [allPeople count]; 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 j = 0; j < numberOfPhoneNumbers; j++) { NSString *phoneNumber = CFBridgingRelease(ABMultiValueCopyValueAtIndex(phoneNumbers, j)); NSLog(@" phone:%@", phoneNumber); } CFRelease(phoneNumbers); NSLog(@"============================================="); } }

  5. Quiero llamar su atención sobre un detalle bastante clave, a saber, la "Regla de Crear" :

    Las funciones de Core Foundation tienen nombres que indican cuándo posee un objeto devuelto:

    • Funciones de creación de objetos que tienen " Create " incrustado en el nombre;

    • Funciones de duplicación de objetos que tienen " Copy " incrustada en el nombre.

    Si posee un objeto, es su responsabilidad renunciar a la propiedad (utilizando CFRelease) cuando haya terminado con él.

    Esto significa que usted es responsable de liberar cualquier objeto devuelto por cualquier función de Core Foundation con Create o Copy en el nombre. Puede llamar a CFRelease explícitamente (como hice anteriormente con la addressBook y los phoneNumbers ) o, para objetos que admiten el puente gratuito, puede transferir la propiedad a ARC con __bridge_transfer o CFBridgingRelease (como hice anteriormente con allPeople , lastName , firstName , y phoneNumber ).

    El analizador estático (presione shift + command + B en Xcode o elija "Analizar" en el menú "Producto") puede identificar muchas situaciones en las que omitió observar esta "Crear regla" y no pudo liberar los objetos apropiados. Por lo tanto, cada vez que escriba código de Core Foundation como este, siempre ejecútelo a través del analizador estático para asegurarse de que no tenga ninguna fuga obvia.


Esta es una demostración completa para buscar todos los contactos con vista de tabla.

import UIKit import ContactsUI import AddressBook import Contacts class ShowContactsVC: UIViewController,CNContactPickerDelegate,UITableViewDelegate,UITableViewDataSource { @IBOutlet weak var tableView: UITableView! let peoplePicker = CNContactPickerViewController() let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate var contacts = [CNContact]() var option : Int = 0 var userAccessGranted : Bool = false var dataArray : NSMutableArray? override func viewDidLoad() { super.viewDidLoad() peoplePicker.delegate = self self.checkIfUserAccessGranted() self.tableView.delegate = self self.tableView.dataSource = self navigationController!.navigationBar.barTintColor = UIColor.grayColor() if(self.userAccessGranted) { self.tableView.hidden = false fetchContacts() } } func numberOfSectionsInTableView(tableView: UITableView) -> Int { return 1 } func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { if dataArray == nil { return 0; } else{ return dataArray!.count } } func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier("TableCell", forIndexPath: indexPath) as! ContactsTableViewCell let data = dataArray![indexPath.row] as! Data; cell.lblName.text = data.name cell.imgContact.image = data.image return cell } func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) { cell.backgroundColor = UIColor.cyanColor() } func checkIfUserAccessGranted() { appDelegate.requestForAccess { (accessGranted) -> Void in if accessGranted { self.userAccessGranted = true; }else{ self.userAccessGranted = false; } } } func fetchContacts() { dataArray = NSMutableArray() let toFetch = [CNContactGivenNameKey, CNContactImageDataKey, CNContactFamilyNameKey, CNContactImageDataAvailableKey] let request = CNContactFetchRequest(keysToFetch: toFetch) do{ try appDelegate.contactStore.enumerateContactsWithFetchRequest(request) { contact, stop in print(contact.givenName) print(contact.familyName) print(contact.identifier) var userImage : UIImage; // See if we can get image data if let imageData = contact.imageData { //If so create the image userImage = UIImage(data: imageData)! }else{ userImage = UIImage(named: "no_contact_image")! } let data = Data(name: contact.givenName, image: userImage) self.dataArray?.addObject(data) } } catch let err{ print(err) } self.tableView.reloadData() } func contactPickerDidCancel(picker: CNContactPickerViewController) { picker.dismissViewControllerAnimated(true, completion: nil) self.navigationController?.popToRootViewControllerAnimated(true) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } } import UIKit class Data { let name : String let image : UIImage init(name : String, image : UIImage) { self.image = image self.name = name } }


Esto funciona para ios 7 e ios 8, espero que te ayude .............

NSMutableArray *result = [[NSMutableArray alloc] init]; CFErrorRef *error = nil; ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error); __block BOOL accessGranted = NO; if (ABAddressBookRequestAccessWithCompletion != NULL){ 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); } else{ accessGranted = YES; } if (accessGranted){ // If the app is authorized to access the first time then add the contact ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error); CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook); CFIndex numberOfPeople = ABAddressBookGetPersonCount(addressBook); for (int i=0; i<numberOfPeople; i++){ CFStringRef phone; ABRecordRef person = CFArrayGetValueAtIndex(allPeople, i); CFStringRef firstName = ABRecordCopyValue(person, kABPersonFirstNameProperty); CFStringRef lastName = ABRecordCopyValue(person, kABPersonLastNameProperty); NSString *userName = @"NoName"; userName = [NSString stringWithFormat:@"%@ %@", firstName, lastName]; userName = [userName stringByReplacingOccurrencesOfString:@"(null)" withString:@""]; ABMutableMultiValueRef phoneNumbers = ABRecordCopyValue(person, kABPersonPhoneProperty); CFIndex phoneNumberCount = ABMultiValueGetCount( phoneNumbers ); phone = nil; for ( CFIndex ind= 0; ind<phoneNumberCount; ind++ ){ CFStringRef phoneNumberLabel = ABMultiValueCopyLabelAtIndex( phoneNumbers, ind); CFStringRef phoneNumberValue = ABMultiValueCopyValueAtIndex( phoneNumbers, ind); // converts "_$!<Work>!$_" to "work" and "_$!<Mobile>!$_" to "mobile" // Find the ones you want here if (phoneNumberLabel != nil){ NSStringCompareOptions compareOptions = NSCaseInsensitiveSearch; if(CFStringCompare(phoneNumberLabel, CFSTR("mobile"),compareOptions)){ phone = phoneNumberValue; } phone = phoneNumberValue; NSStringCompareOptions compareOptionss = NSCaseInsensitiveSearch; if(!CFStringCompare(phone, CFSTR("1-800-MY-APPLE"),compareOptionss)){ continue; } NSMutableArray *theKeys = [NSMutableArray arrayWithObjects:@"name", @"small_name",@"phone", @"checked", nil]; NSMutableArray *theObjects = [NSMutableArray arrayWithObjects:userName, [userName lowercaseString],phone, @"NO", nil]; NSMutableDictionary *theDict = [NSMutableDictionary dictionaryWithObjects:theObjects forKeys:theKeys]; if (![[functions formatNumber:(__bridge NSString *)(phone)] isEqualToString:[[NSUserDefaults standardUserDefaults]valueForKey:@"phoneNumber"]]){ [result addObject:theDict]; } } } } } //sort array NSSortDescriptor * descriptor = [[NSSortDescriptor alloc] initWithKey:@"small_name" ascending:YES]; // 1 NSArray * sortedArray = [result sortedArrayUsingDescriptors:[NSArray arrayWithObject:descriptor]];


Gracias a mahesh y wzbozon, el siguiente código funcionó para mí:

CFErrorRef * error = NULL; addressBook = ABAddressBookCreateWithOptions(NULL, error); ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) { if (granted) { dispatch_async(dispatch_get_main_queue(), ^{ 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); NSMutableArray *numbers = [NSMutableArray array]; for (CFIndex i = 0; i < ABMultiValueGetCount(phoneNumbers); i++) { NSString *phoneNumber = (__bridge_transfer NSString *) ABMultiValueCopyValueAtIndex(phoneNumbers, i); [numbers addObject:phoneNumber]; } NSMutableDictionary *contact = [NSMutableDictionary dictionary]; [contact setObject:name forKey:@"name"]; [contact setObject:numbers forKey:@"numbers"]; [all_contacts addObject:contact]; } }); } });


Use este código para mostrar todos los nombres + apellidos + números de teléfono (iOS 6). Funciona en el simulador también:

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


Versión Swift:

override func viewDidLoad() { super.viewDidLoad() var error: Unmanaged<CFErrorRef>? var addressBook: ABAddressBook = ABAddressBookCreateWithOptions(nil, &error).takeRetainedValue() if ABAddressBookGetAuthorizationStatus() == ABAuthorizationStatus.NotDetermined { ABAddressBookRequestAccessWithCompletion(addressBook, { (granted:Bool, error:CFErrorRef!) -> Void in self.populateFrom(addressBook: addressBook) }) } else if ABAddressBookGetAuthorizationStatus() == ABAuthorizationStatus.Authorized { self.populateFrom(addressBook: addressBook) } } func populateFrom(#addressBook:ABAddressBook){ let allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook).takeRetainedValue() let nPeople = ABAddressBookGetPersonCount(addressBook) for index in 0..<nPeople{ let person: ABRecordRef = Unmanaged<ABRecordRef>.fromOpaque(COpaquePointer(CFArrayGetValueAtIndex(allPeople, index))).takeUnretainedValue() let firstName: String = ABRecordCopyValue(person, kABPersonFirstNameProperty).takeUnretainedValue() as? String println("/(firstName.debugDescription)") } }


si desea ordenar alfabéticamente, puede usar el código siguiente.

CFErrorRef *error = NULL; ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error); CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook); CFIndex numberOfPeople = ABAddressBookGetPersonCount(addressBook); CFMutableArrayRef peopleMutable = CFArrayCreateMutableCopy(kCFAllocatorDefault, CFArrayGetCount(allPeople), allPeople); CFArraySortValues(peopleMutable, CFRangeMake(0, CFArrayGetCount(peopleMutable)), (CFComparatorFunction) ABPersonComparePeopleByName, kABPersonSortByFirstName);


Actualización para iOS 9.0 . Apple ha desaprobado la AddressBook y ahora han agregado el marco de Contacts :

Agregue la propiedad CNContactStore y CNContactStore esta manera:

self.contactsStrore = [[CNContactStore alloc] init];

A continuación, agregue estos métodos para leer todos los contactos:

-(void)checkContactsAccess{ [self requestContactsAccessWithHandler:^(BOOL grandted) { if (grandted) { CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:@[CNContactFamilyNameKey, CNContactGivenNameKey, CNContactNamePrefixKey, CNContactMiddleNameKey, CNContactPhoneNumbersKey]]; [self.contactsStrore enumerateContactsWithFetchRequest:request error:nil usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop) { NSLog(@"%@", contact.familyName); NSLog(@"%@", contact.givenName); NSLog(@"%@", contact.namePrefix); NSLog(@"%@", contact.middleName); NSLog(@"%@", contact.phoneNumbers); NSLog(@"============================================="); }]; } }]; } -(void)requestContactsAccessWithHandler:(void (^)(BOOL grandted))handler{ switch ([CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts]) { case CNAuthorizationStatusAuthorized: handler(YES); break; case CNAuthorizationStatusDenied: case CNAuthorizationStatusNotDetermined:{ [self.contactsStrore requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) { handler(granted); }]; break; } case CNAuthorizationStatusRestricted: handler(NO); break; } }

Antes de iOS 9.0 => Usar el marco de AddressBook . Primero debe verificar el acceso y solicitar acceso a los contactos del Usuario:

// Prompt the user for access to their Address Book data -(void)requestAddressBookAccess { YourViewController * __weak weakSelf = self; ABAddressBookRequestAccessWithCompletion(self.addressBook, ^(bool granted, CFErrorRef error) { if (granted) { dispatch_async(dispatch_get_main_queue(), ^{ [weakSelf accessGrantedForAddressBook]; }); } }); } -(void)checkAddressBookAccess { switch (ABAddressBookGetAuthorizationStatus()) { // Update our UI if the user has granted access to their Contacts case kABAuthorizationStatusAuthorized: [self accessGrantedForAddressBook]; break; // Prompt the user for access to Contacts if there is no definitive answer case kABAuthorizationStatusNotDetermined : [self requestAddressBookAccess]; break; // Display a message if the user has denied or restricted access to Contacts case kABAuthorizationStatusDenied: case kABAuthorizationStatusRestricted: { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Privacy Warning" message:@"Permission was not granted for Contacts." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alert show]; } break; default: break; } }


ABAddressBookRef addressBook = ABAddressBookCreate( ); CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople( addressBook ); CFIndex nPeople = ABAddressBookGetPersonCount( addressBook ); for ( int i = 0; i < nPeople; i++ ) { ABRecordRef ref = CFArrayGetValueAtIndex( allPeople, i ); ... }