Solicitar programáticamente acceso a los contactos

Desde que actualicé a iOS 6 me di cuenta de que mi código para agregar un contacto a la libreta de direcciones de iPhone ya no funciona. Creo que este es un problema relacionado con permisos, ya que Apple ahora requiere permiso del usuario antes de acceder a los contactos (solucionando este problema).

Esperaba que la aplicación solicitara automáticamente permiso para acceder a los contactos, como en la captura de pantalla siguiente, pero no es así. Intentar agregar el contacto simplemente falla con ABAddressBookErrorDomain error 1 .

¿Debo iniciar programáticamente el acceso al cuadro de diálogo de solicitud de contactos? ¿Cómo se hace eso?

acceder a los contactos

Según esta documentación en el sitio de Apple (desplácese hacia abajo a Privacidad en el medio de la página), el acceso a la libreta de direcciones debe otorgarse antes de que se pueda acceder mediante progtwigción. Esto es lo que terminé haciendo.

  #import  // Request authorization to Address Book ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, NULL); if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined) { ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error) { if (granted) { // First time access has been granted, add the contact [self _addContactToAddressBook]; } else { // User denied access // Display an alert telling user the contact could not be added } }); } 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 } 

Actualización para iOS 9 y posterior:

Desde el sitio web de Apple:

Importante

El marco de la interfaz de usuario de la libreta de direcciones está obsoleto en iOS 9. En su lugar, use las API definidas en el marco de ContactsUI. Para obtener más información, consulte ContactsUI

¡Ese fue el truco perfecto para mí!

En iOS6, Apple introduce un nuevo control de privacidad, el usuario puede controlar el acceso de contacto y el calendario de cada aplicación. Por lo tanto, en el lado del código, debe agregar alguna forma de solicitar el permiso. En iOS5 o antes, siempre podemos llamar

 ABAddressBookRef addressBook = ABAddressBookCreate(); 

para obtener la libreta de direcciones sin ningún problema, pero en iOS6, si no tiene permiso, esta llamada simplemente devolverá el puntero vacío. Por eso tenemos que cambiar el método para obtener ABAddressBookRef.

 __block BOOL accessGranted = NO; if (ABAddressBookRequestAccessWithCompletion != NULL) { // we're on iOS 6 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 { // we're on iOS 5 or older accessGranted = YES; } if (accessGranted) { // Do whatever you want here. } 

En el código, el semáforo se usa para bloquear hasta la respuesta, mientras que ABAddressBookRequestAccessWithCompletion solicitará permiso si la aplicación no lo hizo antes. De lo contrario, solo seguirá las configuraciones en Configuración-Privacidad-Contacto.

FUENTE: http://programmerjoe.blogspot.com/2012/10/ios6-permissions-contacts.html

Para el marco de contactos:

 - (void)checkPermissionForCNContacts { switch ([CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts]) { case CNAuthorizationStatusNotDetermined: { [[[CNContactStore alloc] init] requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) { if (granted == YES) [self showCNContactPicker]; }]; } break; case CNAuthorizationStatusRestricted: case CNAuthorizationStatusDenied: // Show custom alert break; case CNAuthorizationStatusAuthorized: [self showCNContactPicker]; break; } } 
 ABAddressBookRef addressBook = ABAddressBookCreate(); __block BOOL accessGranted = NO; if (ABAddressBookRequestAccessWithCompletion != NULL) { // we're on iOS 6 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 { // we're on iOS 5 or older accessGranted = YES; } if (accessGranted) { if(self.isContactsChanged) { { self.isContactsChanged=NO; CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook); ABAddressBookRegisterExternalChangeCallback(addressBook, addressBookChanged, self); int allPeopleCount = CFArrayGetCount(allPeople); NSMutableArray *contactArrTemp = [[NSMutableArray alloc]init]; __block int noNumberCount=1; managedObjectContext = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext]; newMoc = [[NSManagedObjectContext alloc] init]; [newMoc setPersistentStoreCoordinator:[[AppDelegate getAppDelegate] persistentStoreCoordinator]]; [self DeleteAllPhoneContact]; NSNotificationCenter *notify = [NSNotificationCenter defaultCenter]; [notify addObserver:self selector:@selector(mergeChanges:) name:NSManagedObjectContextDidSaveNotification object:newMoc]; self.backgroundQueue = dispatch_queue_create("com.storephonecontacts.bgqueue", NULL); __block NSMutableDictionary *dic; __block NSString *strTime,*strName,*strMobile,*strEmail,*strNotes; __block NSDate *nsDate; dispatch_async(self.backgroundQueue, ^{ NSMutableDictionary *dict =nil; for (int i = 0; i < allPeopleCount; i++) { dic = [[NSMutableDictionary alloc]init]; ABRecordRef record = CFArrayGetValueAtIndex(allPeople,i); NSDate *date = (NSDate*)ABRecordCopyValue(record, kABPersonCreationDateProperty); nsDate = [date retain]; NSDateFormatter *formatterTime = [[NSDateFormatter alloc] init]; [formatterTime setDateFormat:@"hh.mm"]; NSString *dateStrPhone = [formatterTime stringFromDate:date]; strTime = [dateStrPhone retain]; [formatterTime release]; NSString *name = (NSString*)ABRecordCopyValue(record, kABPersonFirstNameProperty); if([name length]>0) name = [name stringByAppendingString:@" "]; NSString *name1 = (NSString*)ABRecordCopyValue(record, kABPersonLastNameProperty); if([name1 length]>0) { if([name length]>0) name = [name stringByAppendingString:name1]; else name = (NSString*)ABRecordCopyValue(record, kABPersonLastNameProperty); } if([name length]>0) strName = [name retain]; else strName = [@"noName" retain]; //to save notes NSString *notes = (NSString*)ABRecordCopyValue(record, kABPersonNoteProperty); if(notes == NULL){ strNotes = @"noNotes"; } else{ strNotes = [notes retain]; } //for image if (!ABPersonHasImageData(record)){ } else{ CFDataRef imageData = ABPersonCopyImageData(record); UIImage *image = [UIImage imageWithData:(NSData *) imageData]; [dic setObject:image forKey:@"image"]; CFRelease(imageData); } //To set Mobile NSMutableArray* mobileArray = [[NSMutableArray alloc] init]; ABMutableMultiValueRef multi = ABRecordCopyValue(record, kABPersonPhoneProperty); if (ABMultiValueGetCount(multi) > 0) { // collect all emails in array for (CFIndex i = 0; i < ABMultiValueGetCount(multi); i++) { CFStringRef mobileRef = ABMultiValueCopyValueAtIndex(multi, i); CFStringRef locLabel = ABMultiValueCopyLabelAtIndex(multi, i); NSString *phoneLabel =(NSString*) ABAddressBookCopyLocalizedLabel(locLabel); if([phoneLabel isEqualToString:@"mobile"]) [mobileArray addObject:(NSString *)mobileRef]; else if([phoneLabel isEqualToString:@"iPhone"]) [mobileArray addObject:(NSString *)mobileRef]; else if([phoneLabel isEqualToString:@"home"]) [mobileArray addObject:(NSString *)mobileRef]; else if([phoneLabel isEqualToString:@"work"]) [mobileArray addObject:(NSString *)mobileRef]; else if([phoneLabel isEqualToString:@"main"]) [mobileArray addObject:(NSString *)mobileRef]; else if([phoneLabel isEqualToString:@"other"]) [mobileArray addObject:(NSString *)mobileRef]; CFRelease(mobileRef); CFRelease(locLabel); } } CFRelease(multi); if([mobileArray count]>0) strMobile = [[mobileArray objectAtIndex:0]retain]; else{ NSString *str=[NSString stringWithFormat:@"noNumber%i",noNumberCount]; strMobile = [str retain]; noNumberCount++; } [mobileArray release]; //To set E-mail NSMutableArray* emailArray = [[NSMutableArray alloc] init]; multi = ABRecordCopyValue(record, kABPersonEmailProperty); if (ABMultiValueGetCount(multi) > 0) { // collect all emails in array for (CFIndex i = 0; i < ABMultiValueGetCount(multi); i++) { CFStringRef emailRef = ABMultiValueCopyValueAtIndex(multi, i); [emailArray addObject:(NSString *)emailRef]; CFRelease(emailRef); } } CFRelease(multi); if([emailArray count]>0) strEmail = [[emailArray objectAtIndex:0]retain]; else strEmail = [@"noemail" retain]; [emailArray release]; bool addBool = NO; if([strName isEqualToString:@"noName"]){ if([strEmail isEqualToString:@"noemail"]){ } else{ [dic setObject:strEmail forKey:@"name"]; addBool = YES; } if(addBool == NO){ if([strMobile isEqualToString:@"noNumber"]){ } else{ [dic setObject:strMobile forKey:@"name"]; addBool = YES; } } } else{ [dic setObject:strName forKey:@"name"]; addBool = YES; } [dic setObject:strEmail forKey:@"email"]; [dic setObject:strMobile forKey:@"mobile"]; [dic setObject:nsDate forKey:@"date"]; [dic setObject:strTime forKey:@"time"]; [dic setObject:strNotes forKey:@"notes"]; if(addBool == YES) [contactArrTemp addObject:dic]; if([strMobile hasPrefix:@"0"]){ NSString *contactNumber=[strMobile stringByReplacingCharactersInRange:NSMakeRange(0, 1) withString:@""]; if(contactNumber.length>7) [dic setObject:@"iPhone" forKey:@"ContactType"]; } else { if(strMobile.length>9) [dic setObject:@"iPhone" forKey:@"ContactType"]; } if(![[dic objectForKey:@"ContactType"] isKindOfClass:[NSNull class]] && [dic objectForKey:@"ContactType"]) { [self InsertContactWithContactInfoDictionary:dic]; } [strName release]; [nsDate release]; [strEmail release]; [strMobile release]; [strTime release]; [strNotes release]; [dic release]; } dispatch_async(self.backgroundQueue, ^(void){ [self gcdDidFinishaddfebriteParsing:dict]; }); dispatch_release(self.backgroundQueue); self.backgroundQueue=nil; }); } } else { [[NSNotificationCenter defaultCenter] postNotificationName:@"PhoneContactsSaved" object:nil userInfo:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:@"Successful"]]; [[NSNotificationCenter defaultCenter] postNotificationName:@"updateContacts" object:nil userInfo:[NSDictionary dictionaryWithObject:@"success" forKey:@"update"]]; } } 

Tuve algunos problemas con el código yunas en iOS6.1 en Xcode5. Con algunas pequeñas adaptaciones funcionó para mí.

El problema era que ARC en iOS 6 no permitía dispatch_release(sema); Aquí está el código de trabajo. Nota: ¡Utilizo m_addressbook lugar de la addressbook de addressbook como ABAddressBookRef!

ViewController.m

 #import "ViewController.h" #import  #import  #import  @interface ViewController () @property (nonatomic, strong) NSMutableArray* contactList; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; ABAddressBookRef m_addressbook = ABAddressBookCreateWithOptions(NULL, NULL); __block BOOL accessGranted = NO; if (ABAddressBookRequestAccessWithCompletion != NULL) { // we're on iOS 6 dispatch_semaphore_t sema = dispatch_semaphore_create(0); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ @autoreleasepool { // Write your code here... // Fetch data from SQLite DB } }); ABAddressBookRequestAccessWithCompletion(m_addressbook, ^(bool granted, CFErrorRef error) { accessGranted = granted; dispatch_semaphore_signal(sema); }); dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); } else { // we're on iOS 5 or older accessGranted = YES; } if (accessGranted) { // do your stuff } } // ... 
 - (void)viewDidLoad { [super viewDidLoad]; [self loadPhoneContacts]; } -(void)loadPhoneContacts{ 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); } } - (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(@"============================================="); } } 

Si alguien tiene un problema con la libreta de direcciones en iOS5, utilice

 ABAddressBookRef addressBook = ABAddressBookCreate(); 

Insistido de

 ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL,NULL); 
 ABAddressBookRequestAccessWithCompletion(ABAddressBookCreateWithOptions(NULL, nil), ^(bool granted, CFErrorRef error) { dispatch_async(dispatch_get_main_queue(), ^{ if (!granted){ [[[UIAlertView alloc] initWithTitle:@"Contacts Access Denied" message:@"This app requires access to your device's Contacts.\n\nPlease enable Contacts access for this app in Settings / Privacy / Contacts" delegate:nil cancelButtonTitle:@"Dismiss" otherButtonTitles:nil] show]; } else { //access authorized } }); }); 

Para agregar una descripción para alertar el uso en InfoPlist.strings.

NSContactsUsageDescription = "TESTING!";

Swift 3. No te olvides de importar Contactos

 func requestForContactAccess(completionHandler: @escaping (_ accessGranted: Bool) -> Void) { let authorizationStatus = CNContactStore.authorizationStatus(for: CNEntityType.contacts) switch authorizationStatus { case .authorized: completionHandler(true) case .denied, .notDetermined: self.contactStore.requestAccess(for: CNEntityType.contacts, completionHandler: { (access, accessError) -> Void in if access { completionHandler(access) } else { if authorizationStatus == CNAuthorizationStatus.denied { DispatchQueue.main.async(execute: { () -> Void in let message = "\(accessError!.localizedDescription)\n\nPlease allow the app to access your contacts through the Settings." self.showMessage(message: message) }) } } }) default: completionHandler(false) } } 

Con iOS 6 tienes que pedir permiso como este

 requestAccessToEntityType:EKEntityTypeEvent completion: 

Para obtener la libreta de direcciones en ios

 - (void)retreiveAllContacts { ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL); CFArrayRef people = ABAddressBookCopyArrayOfAllPeople(addressBook); if (!people) { return ; } CFMutableArrayRef peopleMutable = CFArrayCreateMutableCopy(kCFAllocatorDefault, CFArrayGetCount(people), people); CFArraySortValues(peopleMutable, CFRangeMake(0, CFArrayGetCount(peopleMutable)), (CFComparatorFunction) ABPersonComparePeopleByName, (void*) ABPersonGetSortOrdering()); NSMutableArray *contacts = [[NSMutableArray alloc] initWithCapacity:CFArrayGetCount(peopleMutable)]; for (CFIndex i = 0; i < CFArrayGetCount(peopleMutable); i++) { ABRecordRef person = CFArrayGetValueAtIndex(peopleMutable, i); int32_t recId = ABRecordGetRecordID(person); NSString * abId = [NSString stringWithFormat:@"%d", recId]; ABMultiValueRef phoneNumbers = ABRecordCopyValue(person, kABPersonPhoneProperty); ABMultiValueRef emailIds = ABRecordCopyValue(person, kABPersonEmailProperty); NSString* firstName = (__bridge NSString*)ABRecordCopyValue(person, kABPersonFirstNameProperty); NSString* lastName = (__bridge NSString*)ABRecordCopyValue(person, kABPersonLastNameProperty); NSString* companyName = (__bridge NSString*)ABRecordCopyValue(person, kABPersonOrganizationProperty); NSString* displayName = [firstName ? firstName : @"" stringByAppendingFormat:@" %@", lastName ? lastName : @""]; displayName = [displayName stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@" "]]; NSMutableDictionary* contactInfo = [[NSMutableDictionary alloc] init]; if(ABPersonHasImageData(person)) { CFDataRef imageDataRef = ABPersonCopyImageDataWithFormat(person, kABPersonImageFormatThumbnail); NSData * imageData = (__bridge NSData *)imageDataRef; UIImage * thumbImage = [UIImage imageWithData:imageData]; [contactInfo setObject:thumbImage forKey:@"picture"]; } if(!firstName) firstName = @""; if (!lastName) lastName = @""; if(!displayName) displayName = @""; if(!companyName) companyName = @""; // [contactInfo setObject:[firstName capitalizedString] forKey:kFirstNameKey]; //[contactInfo setObject:[lastName capitalizedString] forKey:kLastNameKey]; [contactInfo setObject:[displayName capitalizedString] forKey:@"name"]; [contactInfo setObject:abId forKey:@"ABID"]; // [contactInfo setObject:companyName forKey:kCompanyNameKey]; NSMutableArray* phoneNumbersList = [[NSMutableArray alloc] init]; for (CFIndex j=0; j < ABMultiValueGetCount(phoneNumbers); j++) { NSString* phone = (__bridge NSString*)ABMultiValueCopyValueAtIndex(phoneNumbers, j); CFStringRef localizedLabel = ABMultiValueCopyLabelAtIndex(phoneNumbers,j); // NSString *phoneLabel =(__bridge NSString*) ABAddressBookCopyLocalizedLabel(localizedLabel); if( phone) { // NSLog(@"validatedPhone: %@", validatedPhone); [phoneNumbersList addObject:phone]; } if (localizedLabel) { // NSLog(@"localizedLabel: %@", localizedLabel); CFRelease(localizedLabel); } } if(phoneNumbers) { // NSLog(@"phoneNumbers: %@", phoneNumbers); CFRelease(phoneNumbers); // NSLog(@"phoneNumbers Release: %@", phoneNumbers); } [contactInfo setObject:phoneNumbersList forKey:@"phoneNumbers"]; NSMutableArray * emailList = [[NSMutableArray alloc] init]; for (CFIndex j=0; j < ABMultiValueGetCount(emailIds); j++) { NSString* email = (__bridge NSString*)ABMultiValueCopyValueAtIndex(emailIds, j); CFStringRef localizedLabel = ABMultiValueCopyLabelAtIndex(emailIds, j); if(email) { [emailList addObject:email]; } } if(emailIds) { CFRelease(emailIds); } if(emailList && [emailList count]) [contactInfo setObject:emailList forKey:@"emails"]; if ([phoneNumbersList count] > 0 || [emailList count] > 0) { [contacts addObject:contactInfo]; } } //CFRelease(); CFRelease(people); if([contacts count]) { [self createiOSContactsDataSourceWithFeed:contacts]; } } 

Este código muestra cómo establecer el permiso y cómo obtener todos los contactos del teléfono y mostrar los contactos en la lista con la etiqueta

 var contactStore = CNContactStore() var contactArray = [CNContact]() func getContacts() { if CNContactStore.authorizationStatus(for: .contacts) == .notDetermined { contactStore.requestAccess(for: .contacts, completionHandler: { (authorized:Bool, error:Error?) in if authorized { let requestForContacts = CNContactFetchRequest(keysToFetch: [CNContactFormatter.descriptorForRequiredKeys(for: CNContactFormatterStyle.fullName), CNContactPhoneNumbersKey as CNKeyDescriptor, CNContactImageDataKey as CNKeyDescriptor, CNContactNicknameKey as CNKeyDescriptor]) do{ try self.contactStore.enumerateContacts(with: requestForContacts) { (contacts : CNContact, stop: UnsafeMutablePointer) -> Void in self.contactArray.append(contacts) //print("hello") } } catch { print("EXCEPTION COUGHT") } } }) } else if CNContactStore.authorizationStatus(for: .contacts) == .authorized { let requestForContacts = CNContactFetchRequest(keysToFetch: [CNContactFormatter.descriptorForRequiredKeys(for: CNContactFormatterStyle.fullName), CNContactPhoneNumbersKey as CNKeyDescriptor, CNContactImageDataKey as CNKeyDescriptor, CNContactNicknameKey as CNKeyDescriptor]) do{ try self.contactStore.enumerateContacts(with: requestForContacts) { (contacts : CNContact, stop: UnsafeMutablePointer) -> Void in self.contactArray.append(contacts) } } catch { } } } override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. getContacts() } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { //print(contactArray) return contactArray.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "defaultCell") if cell != nil{ //var dig = String() var hmdig = [String]() let names = contactArray[indexPath.row] print(names) let name1 = names.givenName+" "+names.middleName+" "+names.familyName for number in names.phoneNumbers { let phoneNumber = number.value let dig = (phoneNumber.value(forKey: "digits") as? String)! hmdig.append(dig) } // Set the contact image. if let imageData = names.imageData { let myImage = cell?.viewWithTag(30) as! UIImageView myImage.image = UIImage(data: imageData) } // let niknm = names.nickname let nameLable1 = cell?.viewWithTag(10) as! UILabel nameLable1.text = name1 let nameLable2 = cell?.viewWithTag(20) as? UILabel nameLable2?.text = hmdig.joined(separator: ",\n") // let nameLable3 = cell?.viewWithTag(40) as? UILabel // nameLable3?.text = niknm return cell! } else{ return UITableViewCell() } }