Как получить все записи контактов в iOS 9 с помощью Contacts Framework


большая часть addressbook framework устарела в iOS 9. В новой структуре контактов документация только показывает, как извлечь записи соответствует NSPredicate, а что если я хочу все запись?

18 66

18 ответов:

оба других ответа загружают контакты только из контейнера с помощью defaultContainerIdentifier. В сценарии, где пользователь имеет несколько контейнеров (например, Exchange и учетную запись iCloud, которые используются для хранения контактов), это будет загружать только контакты из учетной записи, настроенной по умолчанию. Поэтому он не будет загружать все контакты по просьбе автора вопроса.

то, что вы, вероятно, захотите сделать вместо этого, это получить все контейнеры и перебирать их, чтобы извлечь все контакты из каждого из них. Следующий фрагмент кода является примером того, как мы делаем это в одном из наших приложений (в Swift):

lazy var contacts: [CNContact] = {
    let contactStore = CNContactStore()
    let keysToFetch = [
        CNContactFormatter.descriptorForRequiredKeysForStyle(.FullName),
        CNContactEmailAddressesKey,
        CNContactPhoneNumbersKey,
        CNContactImageDataAvailableKey,
        CNContactThumbnailImageDataKey]

    // Get all the containers
    var allContainers: [CNContainer] = []
    do {
        allContainers = try contactStore.containersMatchingPredicate(nil)
    } catch {
        print("Error fetching containers")
    }

    var results: [CNContact] = []

    // Iterate all containers and append their contacts to our results array
    for container in allContainers {
        let fetchPredicate = CNContact.predicateForContactsInContainerWithIdentifier(container.identifier)

        do {
            let containerResults = try contactStore.unifiedContactsMatchingPredicate(fetchPredicate, keysToFetch: keysToFetch)
            results.appendContentsOf(containerResults)
        } catch {
            print("Error fetching results for container")
        }
    }

    return results
}()

Цель-C:

//ios 9+
CNContactStore *store = [[CNContactStore alloc] init];
[store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
    if (granted == YES) {
        //keys with fetching properties
        NSArray *keys = @[CNContactFamilyNameKey, CNContactGivenNameKey, CNContactPhoneNumbersKey, CNContactImageDataKey];
        NSString *containerId = store.defaultContainerIdentifier;
        NSPredicate *predicate = [CNContact predicateForContactsInContainerWithIdentifier:containerId];
        NSError *error;
        NSArray *cnContacts = [store unifiedContactsMatchingPredicate:predicate keysToFetch:keys error:&error];
        if (error) {
            NSLog(@"error fetching contacts %@", error);
        } else {
            for (CNContact *contact in cnContacts) {
                // copy data to my custom Contacts class. 
                Contact *newContact = [[Contact alloc] init];
                newContact.firstName = contact.givenName;
                newContact.lastName = contact.familyName;
                UIImage *image = [UIImage imageWithData:contact.imageData];
                newContact.image = image;
                for (CNLabeledValue *label in contact.phoneNumbers) {
                    NSString *phone = [label.value stringValue];
                    if ([phone length] > 0) {
                        [contact.phones addObject:phone];
                    }
                }
            }
        }
    }        
}];

также для получения всех контактов вы можете использовать enumerateContactsWithFetchRequest способ:

CNContactStore *store = [[CNContactStore alloc] init];
[store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
    if (granted == YES) {
        //keys with fetching properties
        NSArray *keys = @[CNContactFamilyNameKey, CNContactGivenNameKey, CNContactPhoneNumbersKey, CNContactImageDataKey];
        CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:keys];
        NSError *error;
        BOOL success = [store enumerateContactsWithFetchRequest:request error:&error usingBlock:^(CNContact * __nonnull contact, BOOL * __nonnull stop) {
            if (error) {
                NSLog(@"error fetching contacts %@", error);
            } else {
                // copy data to my custom Contact class. 
                Contact *newContact = [[Contact alloc] init];
                newContact.firstName = contact.givenName;
                newContact.lastName = contact.familyName;
                // etc.
            }
        }];
    }        
}];

если вы хотите фильтр контактов по имени вы можете использовать это:

Obj-C:

// keys from example above
NSArray *keys = @[CNContactFamilyNameKey, CNContactGivenNameKey, CNContactPhoneNumbersKey, CNContactImageDataKey];
NSArray *cnContacts = [store unifiedContactsMatchingPredicate:[CNContact predicateForContactsMatchingName:@"John Appleseed"] keysToFetch:keys error:&error];

Swift 3:

let store = CNContactStore()
let contacts = try store.unifiedContactsMatchingPredicate(CNContact.predicateForContactsMatchingName("Appleseed"), keysToFetch:[CNContactGivenNameKey, CNContactFamilyNameKey])

официальная документация здесь:https://developer.apple.com/reference/contacts

используя Свифт и контакты основа для извлечения всех контактов, включая имя и номер телефона

import Contacts

let store = CNContactStore()
store.requestAccessForEntityType(.Contacts, completionHandler: {
    granted, error in

    guard granted else {
        let alert = UIAlertController(title: "Can't access contact", message: "Please go to Settings -> MyApp to enable contact permission", preferredStyle: .Alert)
        alert.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
        self.presentViewController(alert, animated: true, completion: nil)
        return
    }

    let keysToFetch = [CNContactFormatter.descriptorForRequiredKeysForStyle(.FullName), CNContactPhoneNumbersKey]
    let request = CNContactFetchRequest(keysToFetch: keysToFetch)
    var cnContacts = [CNContact]()

    do {
        try store.enumerateContactsWithFetchRequest(request){
            (contact, cursor) -> Void in
            cnContacts.append(contact)
        }
    } catch let error {
        NSLog("Fetch contact error: \(error)")
    }

    NSLog(">>>> Contact list:")
    for contact in cnContacts {
        let fullName = CNContactFormatter.stringFromContact(contact, style: .FullName) ?? "No Name"
        NSLog("\(fullName): \(contact.phoneNumbers.description)")
    }
})

получение контакта медленно операция, поэтому вы не должны блокировать основной поток пользовательского интерфейса. Делай CNContactFetchRequest на фоновом потоке. Вот почему я положил код в completionHandler. Он работает на фоновом потоке.

Apple фактически рекомендует enumerateContactsWithFetchRequest из CNContactStore для извлечения всех контактов и не unifiedContactsMatchingPredicate.

Ниже приведен рабочий код для Obj-C.

CNContactStore *store = [[CNContactStore alloc] init];

//keys with fetching properties
NSArray *keys = @[CNContactGivenNameKey, CNContactPhoneNumbersKey]; 
CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:keys];
NSError *error;

[store enumerateContactsWithFetchRequest:request error:&error usingBlock:^(CNContact * __nonnull contact, BOOL * __nonnull stop) {

        // access it this way -> contact.givenName; etc

}];

вот ссылка, где apple рекомендует перечислить функцию: https://developer.apple.com/reference/contacts/cncontactstore/1403266-unifiedcontactsmatchingpredicate?language=objc#discussion

Если ссылка просрочена, вот что Apple писал:

Если совпадения не найдены, этот метод возвращает пустой массив (или nil in случай ошибки). Используйте только предикаты из класса CNContact предикаты. Составные предикаты не поддерживаются этим методом. Надлежащий для унификации возвращаемые контакты могут иметь разные идентификаторы чем вы указываете. чтобы получить все контакты используйте enumerateContactsWithFetchRequest:error:usingBlock:.

получить полное имя, идентификатор электронной почты, номер телефона, фотографию профиля и дату рождения от Contacts Framework в iOS9

#pragma mark
#pragma mark -- Getting Contacts From AddressBook
 -(void)contactsDetailsFromAddressBook{
//ios 9+
CNContactStore *store = [[CNContactStore alloc] init];
[store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
    if (granted == YES) {
        //keys with fetching properties
        NSArray *keys = @[CNContactBirthdayKey,CNContactFamilyNameKey, CNContactGivenNameKey, CNContactPhoneNumbersKey, CNContactImageDataKey, CNContactEmailAddressesKey];
        NSString *containerId = store.defaultContainerIdentifier;
        NSPredicate *predicate = [CNContact predicateForContactsInContainerWithIdentifier:containerId];
        NSError *error;
        NSArray *cnContacts = [store unifiedContactsMatchingPredicate:predicate keysToFetch:keys error:&error];
        if (error) {
            NSLog(@"error fetching contacts %@", error);
        } else {
            NSString *phone;
            NSString *fullName;
            NSString *firstName;
            NSString *lastName;
            UIImage *profileImage;
            NSDateComponents *birthDayComponent;
            NSMutableArray *contactNumbersArray;
            NSString *birthDayStr;
            NSMutableArray *emailArray;
            NSString* email = @"";
            for (CNContact *contact in cnContacts) {
                // copy data to my custom Contacts class.
                firstName = contact.givenName;
                lastName = contact.familyName;
                birthDayComponent = contact.birthday;
                if (birthDayComponent == nil) {
                    // NSLog(@"Component: %@",birthDayComponent);
                    birthDayStr = @"DOB not available";
                }else{
                    birthDayComponent = contact.birthday;
                    NSInteger day = [birthDayComponent day];
                    NSInteger month = [birthDayComponent month];
                    NSInteger year = [birthDayComponent year];
                    // NSLog(@"Year: %ld, Month: %ld, Day: %ld",(long)year,(long)month,(long)day);
                    birthDayStr = [NSString stringWithFormat:@"%ld/%ld/%ld",(long)day,(long)month,(long)year];
                }
                if (lastName == nil) {
                    fullName=[NSString stringWithFormat:@"%@",firstName];
                }else if (firstName == nil){
                    fullName=[NSString stringWithFormat:@"%@",lastName];
                }
                else{
                    fullName=[NSString stringWithFormat:@"%@ %@",firstName,lastName];
                }
                UIImage *image = [UIImage imageWithData:contact.imageData];
                if (image != nil) {
                    profileImage = image;
                }else{
                    profileImage = [UIImage imageNamed:@"placeholder.png"];
                }
                for (CNLabeledValue *label in contact.phoneNumbers) {
                    phone = [label.value stringValue];
                    if ([phone length] > 0) {
                        [contactNumbersArray addObject:phone];
                    }
                }
                ////Get all E-Mail addresses from contacts
                for (CNLabeledValue *label in contact.emailAddresses) {
                    email = label.value;
                    if ([email length] > 0) {
                        [emailArray addObject:email];
                    }
                }
                //NSLog(@"EMAIL: %@",email);
                NSDictionary* personDict = [[NSDictionary alloc] initWithObjectsAndKeys: fullName,@"fullName",profileImage,@"userImage",phone,@"PhoneNumbers",birthDayStr,@"BirthDay",email,@"userEmailId", nil];
                // NSLog(@"Response: %@",personDict);
                [self.contactsArray addObject:personDict];
            }
            dispatch_async(dispatch_get_main_queue(), ^{
                [self.tableViewRef reloadData];
            });
        }
    }
}];
}

Для Swift 4

        var results: [CNContact] = []

        let fetchRequest = CNContactFetchRequest(keysToFetch: [CNContactGivenNameKey as CNKeyDescriptor, CNContactFamilyNameKey as CNKeyDescriptor, CNContactMiddleNameKey as CNKeyDescriptor, CNContactEmailAddressesKey as CNKeyDescriptor,CNContactPhoneNumbersKey as CNKeyDescriptor])

        fetchRequest.sortOrder = CNContactSortOrder.userDefault

        let store = CNContactStore()

        do {
            try store.enumerateContacts(with: fetchRequest, usingBlock: { (contact, stop) -> Void in
                print(contact.phoneNumbers.first?.value ?? "no")
                results.append(contact)

            })
        }
        catch let error as NSError {
            print(error.localizedDescription)
        }

старая версия для результатов swift var содержит все контакты

let contactStore = CNContactStore()
    var results: [CNContact] = []
    do {
        try contactStore.enumerateContactsWithFetchRequest(CNContactFetchRequest(keysToFetch: [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactMiddleNameKey, CNContactEmailAddressesKey,CNContactPhoneNumbersKey])) {
            (contact, cursor) -> Void in
            results.append(contact)
            }
    }
    catch{
        print("Handle the error please")
    }

на swift 3 and Xcode 8 вы можете получить список всех контактов

let keys = [CNContactGivenNameKey ,CNContactImageDataKey,CNContactPhoneNumbersKey]
        var message: String!
        //let request=CNContactFetchRequest(keysToFetch: keys)
        let contactsStore = AppDelegate.AppDel.contactStore
        // Get all the containers
        var allContainers: [CNContainer] = []
        do {
            allContainers = try contactsStore.containers(matching: nil)
        } catch {
            print("Error fetching containers")
        }



        // Iterate all containers and append their contacts to our results array
        for container in allContainers {
            let fetchPredicate = CNContact.predicateForContactsInContainer(withIdentifier: container.identifier)

            do {
                let containerResults = try contactsStore.unifiedContacts(matching: fetchPredicate, keysToFetch: keys as [CNKeyDescriptor])
                self.results.append(contentsOf: containerResults)
                self.tableView.reloadData()
                message="\(self.results.count)"
            } catch {
                print("Error fetching results for container")
            }
        }

сначала получить идентификатор контейнера по умолчанию и использовать предикат, соответствующий идентификатору контейнера

let keysToFetch = [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey]
let containerId = CNContactStore().defaultContainerIdentifier()
let predicate: NSPredicate = CNContact.predicateForContactsInContainerWithIdentifier(containerId)
let contacts = try CNContactStore().unifiedContactsMatchingPredicate(predicate, keysToFetch: keysToFetch)

@rocolitis ' s ответ в swift! Его ответ является наиболее правильным способом сделать это в соответствии с документацией Apple.

let contactStore = CNContactStore()
let keys = [CNContactPhoneNumbersKey, CNContactFamilyNameKey, CNContactGivenNameKey, CNContactNicknameKey] as [CNKeyDescriptor]
let request = CNContactFetchRequest(keysToFetch: keys)

try? contactStore.enumerateContacts(with: request) { (contact, error) in

    // Do something with contact

}

вы, вероятно, должны проверить свой доступ к контактам в первую очередь!

let authorization = CNContactStore.authorizationStatus(for: CNEntityType.contacts)

switch authorization {
case .authorized: break
case .denied: break
case .restricted: break
case .notDetermined: break
}

CNContact в iOS 9

С

#import "ViewController.h"
#import <Contacts/Contacts.h>
@interface ViewController ()
{
  NSMutableArray *arrayTableData;
}

@end

@implementation ViewController

-(void)viewDidLoad
{
  [self fetchContactsandAuthorization];
}


//This method is for fetching contacts from iPhone.Also It asks authorization permission.
-(void)fetchContactsandAuthorization
{
   // Request authorization to Contacts
   CNContactStore *store = [[CNContactStore alloc] init];
   [store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
   if (granted == YES)
   {
      //keys with fetching properties
      NSArray *keys = @[CNContactFamilyNameKey, CNContactGivenNameKey, CNContactPhoneNumbersKey, CNContactImageDataKey];
      NSString *containerId = store.defaultContainerIdentifier;
      NSPredicate *predicate = [CNContact predicateForContactsInContainerWithIdentifier:containerId];
      NSError *error;
      NSArray *cnContacts = [store unifiedContactsMatchingPredicate:predicate keysToFetch:keys error:&error];
      if (error) 
      {
         NSLog(@"error fetching contacts %@", error);
      } 
      else 
      {
            NSString *phone;
            NSString *fullName;
            NSString *firstName;
            NSString *lastName;
            UIImage *profileImage;
            NSMutableArray *contactNumbersArray = [[NSMutableArray alloc]init];
            for (CNContact *contact in cnContacts) {
                // copy data to my custom Contacts class.
                firstName = contact.givenName;
                lastName = contact.familyName;
                if (lastName == nil) {
                    fullName=[NSString stringWithFormat:@"%@",firstName];
                }else if (firstName == nil){
                    fullName=[NSString stringWithFormat:@"%@",lastName];
                }
                else{
                    fullName=[NSString stringWithFormat:@"%@ %@",firstName,lastName];
                }
                UIImage *image = [UIImage imageWithData:contact.imageData];
                if (image != nil) {
                    profileImage = image;
                }else{
                    profileImage = [UIImage imageNamed:@"person-icon.png"];
                }
                for (CNLabeledValue *label in contact.phoneNumbers) {
                    phone = [label.value stringValue];
                    if ([phone length] > 0) {
                        [contactNumbersArray addObject:phone];
                    }
                }
                NSDictionary* personDict = [[NSDictionary alloc] initWithObjectsAndKeys: fullName,@"fullName",profileImage,@"userImage",phone,@"PhoneNumbers", nil];
                [arrayTableData addObject:[NSString stringWithFormat:@"%@",[personDict objectForKey:@"fullName"]]];
                NSLog(@"The contactsArray are - %@",arrayTableData);
            }
            dispatch_async(dispatch_get_main_queue(), ^{
                [tableViewContactData reloadData];
            });
        }
    }
}];
}
@end

выход

The contactsArray are - (
"John Appleseed",
"Kate Bell",
"Anna Haro",
"Daniel Higgins",
"David Taylor",
"Hank Zakroff"
}

SWIFT 2

Fetch полное имя, идентификатор электронной почты, номер телефона, изображение профиля из Contacts Framework в iOS9

Примечание контакты без имени также были обработаны.

Шаг 1

import Contacts

Шаг 2

func fetchContacts(completion: (result: NSMutableArray) -> Void  )
    {
        let finalArrayForContacts = NSMutableArray()
        let contactsArray = NSMutableArray()
        let requestForContacts = CNContactFetchRequest(keysToFetch: [CNContactIdentifierKey, CNContactFormatter.descriptorForRequiredKeysForStyle(CNContactFormatterStyle.FullName), CNContactPhoneNumbersKey ,CNContactThumbnailImageDataKey])
          do{
            try contactStore.enumerateContactsWithFetchRequest(requestForContacts) { (contactStore : CNContact, stop: UnsafeMutablePointer<ObjCBool>) -> Void in
                contactsArray.addObject(contactStore)
            }
        }
        catch {

        }
        if contactsArray.count > 0 {
            let formatter = CNContactFormatter()
            for contactTemp  in contactsArray
            {
                let contactNew = contactTemp as! CNContact
                //Contact Name
                var stringFromContact = formatter.stringFromContact(contactNew)
                if stringFromContact == nil {
                    stringFromContact = "Unnamed"
                }


                var imageData = NSData?()
                if contactNew.thumbnailImageData != nil{
                     imageData = contactNew.thumbnailImageData!
                }else{
//         imageData = nil
                }
                var tempArray : NSArray = NSArray()
                if (contactNew.phoneNumbers).count > 0 {
                    tempArray = ((contactNew.phoneNumbers as? NSArray)?.valueForKey("value").valueForKey("digits")) as! NSArray
                    for i in 0  ..< tempArray.count
                    {
                      let newDict = NSMutableDictionary()
                        let phoneNumber : String = (tempArray.objectAtIndex(i)) as! String

                        if phoneNumber.characters.count > 0 {
                            var test = false

                            if phoneNumber.hasPrefix("+")
                            {
                                test = true
                            }
                            var resultString : String = (phoneNumber.componentsSeparatedByCharactersInSet(characterSet) as NSArray).componentsJoinedByString("")

                            if test == true
                            {
                                resultString = "+\(resultString)"
                            }
                            newDict.setValue(resultString, forKey: "contact_phone")
                            newDict.setValue(stringFromContact, forKey: "contact_name")
                            newDict.setValue("0", forKey: "contact_select")
                             newDict.setValue(imageData, forKey: "contact_image")
                            finalArrayForContacts.addObject(newDict)
                        }
                    }
                }else{
                    // no number saved
                }
            }
        }else {
            print("No Contacts Found")
        }
        completion(result: finalArrayForContacts)
    }

Я пытаюсь этот код работает нормально. Я могу получить все контактные данные, используя этот код в swift3 latest framework с помощью контактов:

let requestForContacts = CNContactFetchRequest(keysToFetch: [CNContactIdentifierKey as CNKeyDescriptor, CNContactFormatter.descriptorForRequiredKeys(for: CNContactFormatterStyle.fullName), CNContactPhoneNumbersKey as CNKeyDescriptor ,CNContactImageDataKey as CNKeyDescriptor,CNContactEmailAddressesKey as CNKeyDescriptor,CNContactBirthdayKey as CNKeyDescriptor])
do {
    try self.store.enumerateContacts(with: requestForContacts) { contact, stop in
        print("contact:\(contact)")
        self.contacts.append(contact)
    }
} catch {
    print(error)
}

for contact in self.contacts {
    print(contact)
    let firstName = contact.givenName
    nameArray.append(firstName)
    print("first:\(firstName)")
    let phoneNumber = (contact.phoneNumbers[0].value).value(forKey: "digits")
    phoneNumberArray.append(phoneNumber as! String)
    let emailAddress = contact.emailAddresses[0].value(forKey: "value")
    emailAddressArray.append(emailAddress as! String)
}

ответ Коди в Swift 3:

import Contacts

затем в любой функции вы используете:

           let store = CNContactStore()
            store.requestAccess(for: .contacts, completionHandler: {
                granted, error in

                guard granted else {
                    let alert = UIAlertController(title: "Can't access contact", message: "Please go to Settings -> MyApp to enable contact permission", preferredStyle: .alert)
                    alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
                    self.present(alert, animated: true, completion: nil)
                    return
                }

                let keysToFetch = [CNContactFormatter.descriptorForRequiredKeys(for: .fullName), CNContactPhoneNumbersKey] as [Any]
                let request = CNContactFetchRequest(keysToFetch: keysToFetch as! [CNKeyDescriptor])
                var cnContacts = [CNContact]()

                do {
                    try store.enumerateContacts(with: request){
                        (contact, cursor) -> Void in
                        cnContacts.append(contact)
                    }
                } catch let error {
                    NSLog("Fetch contact error: \(error)")
                }

                print(">>>> Contact list:")
                for contact in cnContacts {
                    let fullName = CNContactFormatter.string(from: contact, style: .fullName) ?? "No Name"
                    print("\(fullName): \(contact.phoneNumbers.description)")
                }
            })

прямо сейчас в iOS9 ABAddressBookRef устарел, поэтому для извлечения всех контактов из телефона используйте эту структуру и добавьте эту функцию, вы получите массив контактов.

импорт контактов в рамках .h класс, как это

#import <Contacts/Contacts.h>

затем добавьте этот метод .файл м

 -(void)contactsFromAddressBook{
//ios 9+
CNContactStore *store = [[CNContactStore alloc] init];
[store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
    if (granted == YES) {
        //keys with fetching properties
        NSArray *keys = @[CNContactFamilyNameKey, CNContactGivenNameKey, CNContactPhoneNumbersKey, CNContactImageDataKey];
        NSString *containerId = store.defaultContainerIdentifier;
        NSPredicate *predicate = [CNContact predicateForContactsInContainerWithIdentifier:containerId];
        NSError *error;
        NSArray *cnContacts = [store unifiedContactsMatchingPredicate:predicate keysToFetch:keys error:&error];
        if (error) {
            NSLog(@"error fetching contacts %@", error);
        } else {
            NSString *phone;
            NSString *fullName;
            NSString *firstName;
            NSString *lastName;
            UIImage *profileImage;
            NSMutableArray *contactNumbersArray;
            for (CNContact *contact in cnContacts) {
                // copy data to my custom Contacts class.
                firstName = contact.givenName;
                lastName = contact.familyName;
                if (lastName == nil) {
                    fullName=[NSString stringWithFormat:@"%@",firstName];
                }else if (firstName == nil){
                    fullName=[NSString stringWithFormat:@"%@",lastName];
                }
                else{
                    fullName=[NSString stringWithFormat:@"%@ %@",firstName,lastName];
                }
                UIImage *image = [UIImage imageWithData:contact.imageData];
                if (image != nil) {
                    profileImage = image;
                }else{
                    profileImage = [UIImage imageNamed:@"person-icon.png"];
                }
                for (CNLabeledValue *label in contact.phoneNumbers) {
                    phone = [label.value stringValue];
                    if ([phone length] > 0) {
                        [contactNumbersArray addObject:phone];
                    }
                }
                NSDictionary* personDict = [[NSDictionary alloc] initWithObjectsAndKeys: fullName,@"fullName",profileImage,@"userImage",phone,@"PhoneNumbers", nil];
                [MutableArray__Contact addObject:personDict];
            }
            dispatch_async(dispatch_get_main_queue(), ^
            {
                NSLog(@"%@",ar_Contact);
                //[self.tableViewRef reloadData];
            });
        }
    }
}];
}

для использования этого метода вызовите функцию contactsFromAddressBook

[self contactsFromAddressBook];

разрешения для контактов iOS 9 SWIFT 2

 let status : CNAuthorizationStatus = CNContactStore.authorizationStatusForEntityType(CNEntityType.Contacts)
        if status == CNAuthorizationStatus.NotDetermined{
            contactStore.requestAccessForEntityType(CNEntityType.Contacts, completionHandler: { (temp: Bool,  error : NSError?) -> Void in
             //call contacts fetching function
            })
        }else if status == CNAuthorizationStatus.Authorized {
             //call contacts fetching function
            })
        }
        else if status == CNAuthorizationStatus.Denied {
            }
    }

здесь swift 3.0 версия flohei это

lazy var contacts: [CNContact] = {
        let contactStore = CNContactStore()
        let keysToFetch = [
            CNContactFormatter.descriptorForRequiredKeys(for: .fullName),
            CNContactPostalAddressesKey,
            CNContactEmailAddressesKey,
            CNContactPhoneNumbersKey,
            CNContactImageDataAvailableKey,
            CNContactThumbnailImageDataKey] as [Any]

        // Get all the containers
        var allContainers: [CNContainer] = []
        do {
            allContainers = try contactStore.containers(matching: nil)
        } catch {
            print("Error fetching containers")
        }

        var results: [CNContact] = []

        // Iterate all containers and append their contacts to our results array
        for container in allContainers {
            let fetchPredicate = CNContact.predicateForContactsInContainer(withIdentifier: container.identifier)

            do {
                let containerResults = try contactStore.unifiedContacts(matching: fetchPredicate, keysToFetch: keysToFetch as! [CNKeyDescriptor])
                results.append(contentsOf: containerResults)
            } catch {
                print("Error fetching results for container")
            }
        }

        return results
    }()

надеюсь, что это помогает!

@flohei ответ Swift-4

 var contacts: [CNContact] = {
        let contactStore = CNContactStore()
        let keysToFetch = [
            CNContactFormatter.descriptorForRequiredKeys(for: CNContactFormatterStyle.fullName),
            CNContactEmailAddressesKey,
            CNContactPhoneNumbersKey,
            CNContactImageDataAvailableKey,
            CNContactThumbnailImageDataKey] as [Any]

        // Get all the containers
        var allContainers: [CNContainer] = []
        do {
            allContainers = try contactStore.containers(matching: nil)
        } catch {
            print("Error fetching containers")
        }

        var results: [CNContact] = []

        // Iterate all containers and append their contacts to our results array
        for container in allContainers {
            let fetchPredicate = CNContact.predicateForContactsInContainer(withIdentifier: container.identifier)

            do {
                let containerResults = try contactStore.unifiedContacts(matching: fetchPredicate, keysToFetch: keysToFetch as! [CNKeyDescriptor])
                results.append(contentsOf: containerResults)
            } catch {
                print("Error fetching results for container")
            }
        }

        return results
    }()

просто хотел поделиться этой версии Swift 4

информация.файл plist:

<key>NSContactsUsageDescription</key>
    <string>$(PRODUCT_NAME) requires to access your contacts ...</string>

модуль:

import Contacts

код:

func fetchContacts(completion: @escaping (_ result: [CNContact]) -> Void){
        DispatchQueue.main.async {
            var results = [CNContact]()
            let keys = [CNContactGivenNameKey,CNContactFamilyNameKey,CNContactMiddleNameKey,CNContactEmailAddressesKey,CNContactPhoneNumbersKey] as [CNKeyDescriptor]
            let fetchRequest = CNContactFetchRequest(keysToFetch: keys)
            fetchRequest.sortOrder = .userDefault
            let store = CNContactStore()
            store.requestAccess(for: .contacts, completionHandler: {(grant,error) in
                if grant{
                    do {
                        try store.enumerateContacts(with: fetchRequest, usingBlock: { (contact, stop) -> Void in
                            results.append(contact)
                        })
                    }
                    catch let error {
                        print(error.localizedDescription)
                    }
                    completion(results)
                }else{
                    print("Error \(error?.localizedDescription ?? "")")
                }
            })
        }
    }

использование:

fetchContacts(completion: {contacts in
            contacts.forEach({print("Name: \(.givenName), number: \(.phoneNumbers.first?.value.stringValue ?? "nil")")})

вам нужно описать информацию об использовании в info.plist в первую очередь. Я добавил проверку, чтобы определить, что пользователь предоставил доступ к контактам, а затем определил ключи (значения должны быть принесенный.) Как сказал в одном из предыдущих ответов, что это трудоемкий процесс, поэтому я добавил DispatchQueue для фоновой обработки и обработчик завершения для возврата массива контактов обратно вызывающему абоненту.