So rufen Sie alle Kontaktdatensätze in iOS 9 mit Contacts Framework ab

75

Der größte Teil des AddressBook-Frameworks ist in iOS 9 veraltet. In der neuen Contacts Framework- Dokumentation wird nur gezeigt, wie Datensätze abgerufen werden, die mit a übereinstimmen. NSPredicateWas ist, wenn ich den gesamten Datensatz möchte ?

Jieyi Hu
quelle

Antworten:

120

Beide anderen Antworten laden nur Kontakte aus dem Container mit dem defaultContainerIdentifier. In einem Szenario, in dem der Benutzer über mehr als einen Container verfügt (dh ein Exchange- und ein iCloud-Konto, die beide zum Speichern von Kontakten verwendet werden), werden nur die Kontakte von dem als Standard konfigurierten Konto geladen. Daher werden nicht alle Kontakte geladen, wie vom Autor der Frage angefordert.

Was Sie wahrscheinlich stattdessen tun möchten, ist, alle Container abzurufen und sie zu durchlaufen, um alle Kontakte aus jedem von ihnen zu extrahieren. Das folgende Code-Snippet ist ein Beispiel dafür, wie wir es in einer unserer Apps (in Swift) machen:

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
}()
flohei
quelle
@flohei Das ist eine gute Antwort! Aber Sie haben das Schlüsselwort "faul" hinzugefügt? Und wie hilft es hier?
Entwickler
1
Ich habe hier nur Lazy-Loading verwendet, weil ich nicht alle Kontakte sofort laden musste. Ich brauchte sie erst, nachdem der Benutzer etwas unternommen hatte.
Flohei
1
Was ist, wenn ich die Methode enumerateContactsWithFetchRequest: error: usingBlock: anstelle des oben genannten Ansatzes verwende. Was ist der Unterschied zwischen ihnen? Bekomme ich auch hier alle Kontakte?
Shyam
3
Laut Apple-Beispiel "ManagingContacts" sollte "enumerateContactsWithFetchRequest" ausreichen, um alle verfügbaren Kontakte abzurufen. Auch das Abrufen sollte nicht in der Hauptwarteschlange erfolgen
Marek H
Ich habe ein Problem bei der Verwendung von contactStore.containersMatchingPredicate (nil) festgestellt. Diese Funktion gibt ein leeres Array zurück. Es gibt jedoch einige Kontakte im Telefon. Dies geschah auf einem iPhone X.
脆 味 嘎 嘣 2
44

Ziel 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];
                    }
                }
            }
        }
    }        
}];

Um alle Kontakte zu erhalten, können Sie auch die folgende enumerateContactsWithFetchRequestMethode verwenden:

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.
            }
        }];
    }        
}];

Wenn Sie Kontakte nach Namen filtern möchten können Sie Folgendes verwenden:

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

Die offizielle Dokumentation finden Sie hier: https://developer.apple.com/reference/contacts

Eridana
quelle
18

Verwenden des Swift and Contacts- Frameworks zum Abrufen aller Kontakte, einschließlich Name und Telefonnummern

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

Das Abrufen von Kontakten ist ein langsamer Vorgang, daher sollten Sie den Haupt-UI-Thread nicht blockieren. Tun Sie CNContactFetchRequestauf Hintergrund-Thread. Deshalb habe ich den Code in CompletionHandler eingefügt. Es wird auf einem Hintergrund-Thread ausgeführt.

Cody
quelle
12

Apple empfiehlt tatsächlich enumerateContactsWithFetchRequest von CNContactStore, um alle Kontakte und NICHT unifiedContactsMatchingPredicate abzurufen.

Unten finden Sie den Arbeitscode für 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

}];

Hier ist der Link, unter dem Apple die Aufzählungsfunktion empfiehlt: https://developer.apple.com/reference/contacts/cncontactstore/1403266-unifiedcontactsmatchingpredicate?language=objc#discussion

Wenn der Link abgelaufen ist, hat Apple Folgendes geschrieben:

Wenn keine Übereinstimmungen gefunden werden, gibt diese Methode ein leeres Array zurück (oder im Fehlerfall null). Verwenden Sie nur die Prädikate aus den Prädikaten der CNContact-Klasse. Zusammengesetzte Prädikate werden von dieser Methode nicht unterstützt. Aufgrund der Vereinheitlichung haben die zurückgegebenen Kontakte möglicherweise andere Kennungen als von Ihnen angegeben. Verwenden Sie zum Abrufen aller KontakteenumerateContactsWithFetchRequest:error:usingBlock: .

GeneCode
quelle
Ist das Lambda ein blockierender / synchroner Anruf?
Mr5
9

Für 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)
        }

Die ältere Version für schnelle Var-Ergebnisse enthält alle Kontakte

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")
    }
JD
quelle
Wie wir dies in Ziel C implementieren können
user3306145
7

Vollständigen Namen, E-Mail-ID, Telefonnummer, Profilbild und Geburtstagsdatum erhalten Sie vom Contacts Framework in 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];
            });
        }
    }
}];
}
Mannam Brahmam
quelle
Aber ich bekomme keine Namen für einige Kontakte. Bitte helfen Sie mir, ich bekomme Nein mit leeren Vor- und Nachnamen.
user3306145
@ user3306145, Verwenden Sie den gleichen Code, den ich oben erwähnt habe
Mannam Brahmam
Sie sind die einzige Person, die mit dem obigen Code erwähnt, dass Sie keine Kontaktnamen (Vor- und Nachname) abrufen können. Bitte überprüfen Sie in Ihrem Adressbuch, ob alle Kontakte durch Referenz von Vorname und Nachname
Mannam Brahmam
Lassen Sie uns diese Diskussion im Chat fortsetzen .
Mannam Brahmam
6

In swift 3 and Xcode 8können Sie alle Kontaktlisten erhalten

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")
            }
        }
Mahesh Giri
quelle
6

@rocolitis 'Antwort schnell! Seine Antwort ist laut Apples Dokumentation der richtigste Weg, dies zu tun.

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

}

Sie sollten wahrscheinlich zuerst Ihren Zugriff auf Ihre Kontakte überprüfen!

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

switch authorization {
case .authorized: break
case .denied: break
case .restricted: break
case .notDetermined: break
}
Reid
quelle
1
Ich konnte NICHT herausfinden, "was" keysToFetch sein sollte. Mir ist nie in den Sinn gekommen, dass ich nur das Array von Strings als Array von CNKeyDescriptor umwandeln musste. Vielen Dank!
Ghostatron
Kein Problem! Bitte stimme meiner Antwort zu, damit mehr Leute sie sehen können!
Reid
5

Holen Sie sich zuerst die Standard-Container-ID und verwenden Sie die Prädikat-Matching-Container-ID

let keysToFetch = [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey]
let containerId = CNContactStore().defaultContainerIdentifier()
let predicate: NSPredicate = CNContact.predicateForContactsInContainerWithIdentifier(containerId)
let contacts = try CNContactStore().unifiedContactsMatchingPredicate(predicate, keysToFetch: keysToFetch)
Jieyi Hu
quelle
Wie werden alle Kontakte abgerufen? Ruft dies nicht nur die Kontakte aus dem Standardcontainer ab? Was ist mit anderen Containern?
Flohei
4

CNContact in iOS 9

Ziel c

#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

Die Ausgabe ist

The contactsArray are - (
"John Appleseed",
"Kate Bell",
"Anna Haro",
"Daniel Higgins",
"David Taylor",
"Hank Zakroff"
}
user3182143
quelle
Es zeigt nur einige der Kontakte .. wie man alle Kontakte auf meinem iPhone
Hari Narayanan
Überprüfen Sie es von Ihrem Originalgerät
user3182143
Vielen Dank @ user3182143 Ich bin Kontaktabrufanforderung verwendet, um das Problem zu lösen CNContactFetchRequest * fetchRequest = [[CNContactFetchRequest alloc] initWithKeysToFetch: keys]; und dann im Array speichern [store enumerateContactsWithFetchRequest: fetchRequest error: nil usingBlock: ^ (CNContact * _Nonnull contact, BOOL * _Nonnull stop) {[contact_array addObject: contact]; // Objekte aller Kontaktlisten im Array hinzufügen NSLog (@ "mutable_copy count:% lu", (unsigned long) contact_array.count); }];
Hari Narayanan
3

SWIFT 2

Abrufen des vollständigen Namens, der E-Mail-ID, der Telefonnummer und des Profilbilds aus dem Contacts Framework in iOS9

HINWEIS Kontakte ohne Namen wurden ebenfalls behandelt.

Schritt 1

import Contacts

Schritt 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)
    }
Maninderjit Singh
quelle
3

Update 1:
Hier ist die Swift 5Version:

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

        // 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)
                results.append(contentsOf: containerResults)
            } catch {
                print("Error fetching results for container")
            }
        }

        return results
    }()

Ursprüngliche Antwort:
Hier ist die Swift 3.0Version von Floheis Antwort

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

Hoffe das hilft!

S1LENT WARRIOR
quelle
Diese einzige Abrufliste unterstützt die Benutzeroberfläche nicht. Die Lösung sollte vollständig sein, Daten mit nativer Benutzeroberfläche.
iPhone 7
2

Ich versuche diesen Code, es funktioniert gut. Ich kann alle Kontaktdetails mit diesem Code im neuesten swift3-Framework mithilfe von Kontakten abrufen:

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)
}
Gangireddy Rami Reddy
quelle
2

Codys Antwort in Swift 3:

import Contacts

Dann innerhalb welcher Funktion Sie verwenden:

           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)")
                }
            })
user1333394
quelle
1

Derzeit ist ABAddressBookRef in iOS9 veraltet. Um alle Kontakte vom Telefon abzurufen, verwenden Sie dieses Framework und fügen Sie diese Funktion hinzu. Sie erhalten eine Reihe von Kontakten.

Importieren Sie das Contact Framework in die .h-Klasse wie folgt

#import <Contacts/Contacts.h>

Fügen Sie diese Methode dann in die .m-Datei ein

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

Um diese Methode zu verwenden, rufen Sie die Funktion contactFromAddressBook auf

[self contactsFromAddressBook];
user3189586
quelle
Hallo, ich verwende NSArray * contactList = [NSArray arrayWithArray: [CNContactVCardSerialization contactWithData: dataString error: nil]]; CNContact * contactObject = [contactList objectAtIndex: 0]; und hier kann ich kein Bild des Kontakts abrufen UIImage * image = [UIImage imageFormData: contactObject.imageData.]; plzz Hilfe ...
Abhishek Thapliyal
auf Erlaubnis prüfen CNContactImageDataKey prüft auch, ob ein Bild für die Person vorhanden ist.
user3189586
Bild ist da, aber wenn ich es Bild aus Daten konvertiere, wird es null
Abhishek Thapliyal
Ich analysiere nach VCF-Datei
Abhishek Thapliyal
Sie können dies verwenden, wenn das Bild nicht null ist. NSData * imgData = (NSData *) ABPersonCopyImageData (person); UIImage * img = [UIImage imageWithData: imgData];
user3189586
1

Berechtigungen für Kontakte 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 {
            }
    }
Maninderjit Singh
quelle
1

Ich wollte nur diese Versionen von Swift 4 teilen

info.plist:

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

Modul:

import Contacts

Code:

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

Verwendung:

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

Sie müssen zuerst die Nutzungsinformationen in info.plist beschreiben. Ich habe eine Prüfung hinzugefügt, um festzustellen, ob der Benutzer den Zugriff auf Kontakte gewährt hat, und dann die Schlüssel definiert (die Werte, die abgerufen werden müssen). Wie in einer der früheren Antworten erwähnt, ist dies ein zeitaufwändiger Prozess. Daher habe ich DispatchQueue für die Hintergrundverarbeitung und den Abschlusshandler hinzugefügt, um das Kontaktarray an den Anrufer zurückzugeben.

Sahil Manchanda
quelle
1

Swift 4.2. Kontaktnummern mit Bild abrufen

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

}}

Funktionsaufruf in der Did Load-Methode

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()
        }
    })
}
Shakeel Ahmed
quelle
0

@flohei antworte inSwift-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
    }()
Kiran Jasvanee
quelle
0

Wenn Sie ALLE Felder eines Kontakts mit bekannter Kennung erhalten möchten:

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

Auf diese Weise haben Sie Zugriff auf ALLE Felder wie Adressen, Telefonnummern, vollständigen Namen usw.

So rufen Sie fullName ab:

let fullname = CNContactFormatter.string(from: contact, style: .fullName)
Mari
quelle