How to fetch all contacts record in iOS 9 using Contacts Framework

前端 未结 20 1525
[愿得一人]
[愿得一人] 2020-11-28 01:52

Most part of AddressBook framework is deprecated in iOS 9. In the new Contacts Framework documentation only shows how to fetch records matches a NSPredicate, bu

相关标签:
20条回答
  • 2020-11-28 02:14

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

    Also to get all contacts you can use the enumerateContactsWithFetchRequest method:

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

    If you want to filter contacts by name you can use this:

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

    Official documentation is here: https://developer.apple.com/reference/contacts

    0 讨论(0)
  • 2020-11-28 02:14

    Using Swift and Contacts framework to fetch all contacts, including name and phone numbers

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

    Fetching contact is slow operation, so you should not block main UI thread. Do CNContactFetchRequest on background thread. That's why I put the code into completionHandler. It's run on a background thread.

    0 讨论(0)
  • 2020-11-28 02:14

    Update 1:
    Here is the Swift 5 version:

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

    Original Answer:
    Here is the Swift 3.0 version of flohei's answer

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

    Hope this helps!

    0 讨论(0)
  • 2020-11-28 02:15

    @rocolitis 's answer in swift! His answer is the most correct way of doing this according to Apple's documentation.

    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
    
    }
    

    You should probably check your access to your contacts first!

    let authorization = CNContactStore.authorizationStatus(for: CNEntityType.contacts)
    
    switch authorization {
    case .authorized: break
    case .denied: break
    case .restricted: break
    case .notDetermined: break
    }
    
    0 讨论(0)
  • CNContact in iOS 9

    Objective 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
    

    The output is

    The contactsArray are - (
    "John Appleseed",
    "Kate Bell",
    "Anna Haro",
    "Daniel Higgins",
    "David Taylor",
    "Hank Zakroff"
    }
    
    0 讨论(0)
  • 2020-11-28 02:18

    Get Full Name, Email Id, Phone Number, Profile Picture and Birthday Date from 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];
                });
            }
        }
    }];
    }
    
    0 讨论(0)
提交回复
热议问题