以编程方式请求访问联系人
由于更新到iOS 6我注意到我的代码添加联系人到iPhone的通讯簿不再起作用。 我相信这是一个权限相关的问题,因为苹果现在需要用户权限才能访问联系人(解决这个问题)。
我预计该应用程序会自动请求访问联系人的权限,如下面的屏幕截图所示,但不是。 尝试添加联系人失败,出现ABAddressBookErrorDomain error 1
。
我是否需要以编程方式启动对联系人请求对话框的访问? 这是怎么做的?
根据苹果网站上的文档 (向下滚动到页面中间的隐私), 必须先授予对地址簿的访问权限,然后才能以编程方式访问。 这是我最终做的。
#import <AddressBookUI/AddressBookUI.h> // 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 }
更新对于iOS 9和更高版本:
从苹果网站:
重要
在iOS 9中不推荐使用地址簿UI框架。改为使用ContactsUI框架中定义的API。 要了解更多信息,请参阅ContactsUI
那对我来说完美的伎俩!
在iOS6上,苹果引入新的隐私控制,用户可以通过每个应用程序控制联系和日历的访问。 所以,在代码方面,你需要添加一些方法来请求权限。 在iOS5或之前,我们可以随时致电
ABAddressBookRef addressBook = ABAddressBookCreate();
获取地址簿没有任何问题,但在iOS6中,如果你没有权限,这个调用将只返回空指针。 那为什么我们需要改变方法来获取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. }
在代码中,信号量用于阻塞,直到响应,而ABAddressBookRequestAccessWithCompletion将要求权限,如果应用程序之前没有问。 否则,只需按照设置 – 隐私 – 联系中的设置。
消息来源: http : //programmerjoe.blogspot.com/2012/10/ios6-permissions-contacts.html
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"]]; } }
在Xcode5的iOS6.1上有yunas代码的问题。 随着一些小适应它为我工作。
问题是,iOS 6中的ARC不允许dispatch_release(sema);
这是工作代码。 注意:我使用m_addressbook
代替addressbook
作为ABAddressBookRef!
ViewController.m
#import "ViewController.h" #import <AddressBook/AddressBook.h> #import <AddressBook/ABAddressBook.h> #import <AddressBook/ABPerson.h> @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(@"============================================="); } }
对于联系人框架:
- (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; } }
如果有人在iOS5的地址簿有问题,然后使用
ABAddressBookRef addressBook = ABAddressBookCreate();
绝望的
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 } }); });
用于添加说明以提醒InfoPlist.strings中的使用。
NSContactsUsageDescription = "TESTING!";
Swift 3.不要忘记导入联系人
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) } }
在iOS 6中,你必须要求这样的权限
requestAccessToEntityType:EKEntityTypeEvent completion:
在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]; } }
此代码显示如何设置权限以及如何从手机获取所有联系人,并使用标签标签显示列表中的联系人
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<ObjCBool>) -> 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<ObjCBool>) -> 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() } }