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

Большая часть платформы AddressBook устарела в iOS 9. В новой документации Contacts Framework только показано, как получить записи, соответствующие NSPredicate, но что, если я хочу всю запись?

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
}()

Objective-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];

Свифт 3:

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

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

Использование платформы Swift and 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 на фоне темы. Вот почему я положил код в завершение Handler. Он запускается в фоновом потоке.

Apple фактически рекомендует перечислить ContactsWithFetchRequest из 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

Если срок действия ссылки истек, Apple пишет следующее:

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

Для 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")
    }

Получите полное имя, идентификатор электронной почты, номер телефона, изображение профиля и дату рождения от 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 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")
            }
        }

Ответ @rocolitis в кратчайшие сроки! Его ответ - самый правильный способ сделать это согласно документации 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
}

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

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

Здесь swift 3.0 версия ответа Флоэя

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
    }()

Надеюсь это поможет!

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

Получите полное имя, идентификатор электронной почты, номер телефона, изображение профиля из 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)
    }

Ответ Коди в Свифте 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)")
                }
            })

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

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)
}

Свифт 4.2 . Получить контактные телефоны с изображением

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



//MARK:- Fetch All Contacts of Phone
func fetchContacts(completion: @escaping (_ result: [CNContact]) -> Void){
    DispatchQueue.main.async {
        var results = [CNContact]()
        let keys = [CNContactGivenNameKey,CNContactFamilyNameKey,CNContactMiddleNameKey,CNContactEmailAddressesKey,CNContactPhoneNumbersKey,CNContactThumbnailImageDataKey] 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 ?? "")")
            }
        })
    }
}

}

Вызов функции в методе Did Load

var arrpic = NSMutableArray()

 override func viewDidLoad() {
    super.viewDidLoad()

    fetchContacts(completion: {contacts in
        contacts.forEach({print("Name: \($0.givenName), number: \($0.phoneNumbers.first?.value.stringValue ?? "nil")")
            self.arrfname.append("\($0.givenName)")
            self.arrlname.append("\($0.familyName)")
            self.arrnumber.append("\($0.phoneNumbers.first?.value.stringValue ?? "nil")")
            var img = UIImage()
            if $0.thumbnailImageData != nil
            {
                img = UIImage.init(data: $0.thumbnailImageData!)!
                self.arrpic.add(img)
            }
            else
            {
                self.arrpic.add("")
            }
        })
        if contacts.count > 0
        {
            self.tablev.reloadData()
        }
    })
}

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

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

#import <Contacts/Contacts.h>

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

 -(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];

@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

info.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: \($0.givenName), number: \($0.phoneNumbers.first?.value.stringValue ?? "nil")")})

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

Разрешения для контактов 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 {
            }
    }

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

let contact = unifiedContact(withIdentifier: identifier, keysToFetch: [CNContactVCardSerialization.descriptorForRequiredKeys()])

Это дает вам доступ ко ВСЕМ полям, таким как адреса, номера телефонов, полное имя и т. Д.

Чтобы получить полное имя, тогда:

let fullname = CNContactFormatter.string(from: contact, style: .fullName)
Другие вопросы по тегам