iosobjective-ccncontactstore

How do I get just the street address from CNContacts in Xcode objective-c


I am trying to get just the street address for all the contacts in CNContacts. I have been able to get the givenName and familyName as an NSString and I have been able to get the postalAddress as an array with street, city,zip etc. but I would like to get just the street address out of the array as a string.
Here is my code

 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, CNContactPostalAddressesKey,CNPostalAddressStreetKey,CNPostalAddressCityKey,CNPostalAddressPostalCodeKey];
                                  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) {
                                         NSString *firstNames = contact.givenName;
                                          NSString *lastNames = contact.familyName;
                                    
                                         NSMutableArray *streetName = [[NSMutableArray alloc]initWithObjects:contact.postalAddresses, nil];
                                        
                                         NSLog(@"streets:::%@",streetName); }}}}];

I am using Objective-c and there are few example with Swift but not Objc. Could someone show me how to do this please.


Solution

  • According to the documentation for the postalAddresses property of a CNContact object (https://developer.apple.com/documentation/contacts/cncontact/1403066-postaladdresses?language=objc) it is defined this way:

    NSArray<CNLabeledValue<CNPostalAddress*>*>* postalAddresses;
    

    This means that it contains an array of CNLabeledValue objects that each contain a CNPostalAddress. This allows each postal address to be stored along with a label that describes it and also, for multiple addresses to be stored with the same label.

    enter image description here

    enter image description here

    In the above screen shots, you can see that the user is allowed to choose from any of the 4 predefined labels or create their own custom label (any of which can be used multiple times) when adding an address to a contact.

    CNContactStore* store = [[CNContactStore alloc] init];
    [store requestAccessForEntityType:CNEntityTypeContacts
                    completionHandler:^(BOOL granted, NSError * _Nullable error) {
    
        if (error)
        {
            NSLog(@"Error accessing contacts %@", error.debugDescription);
    
            return;
        }
    
        if (granted)
        {
            NSArray* keys = @[ CNContactFamilyNameKey,
                               CNContactGivenNameKey,
                               CNContactPostalAddressesKey,
                               CNPostalAddressStreetKey,
                               CNPostalAddressCityKey,
                               CNPostalAddressPostalCodeKey
                             ];
    
            NSString* containerId = store.defaultContainerIdentifier;
            NSPredicate* predicate = [CNContact predicateForContactsInContainerWithIdentifier:containerId];
    
            NSError* contactsError;
            NSArray* contacts = [store unifiedContactsMatchingPredicate:predicate
                                                            keysToFetch:keys
                                                                  error:&contactsError];
    
            if (contactsError)
            {
                NSLog(@"Error fetching contacts %@", contactsError.debugDescription);
            }
    
            else
            {
                for (CNContact* contact in contacts)
                {
                    NSString* firstName = contact.givenName;
                    NSString* lastName = contact.familyName;
    
                    NSLog(@"%@ %@:", firstName, lastName);
    
                    for ( CNLabeledValue* lVal in contact.postalAddresses )
                    {
                        // start with the assumption of a custom label
                        NSString* label = lVal.label;
    
                        if ( [CNLabelHome isEqualToString:label] )
                        {
                            label = @"Home";
                        }
    
                        else if ( [CNLabelWork isEqualToString:label] )
                        {
                            label = @"Work";
                        }
    
                        else if ( [CNLabelSchool isEqualToString:label] )
                        {
                            label = @"School";
                        }
    
                        else if ( [CNLabelOther isEqualToString:label] )
                        {
                            label = @"Other";
                        }
    
                        CNPostalAddress* address = (CNPostalAddress*)lVal.value;
    
                        NSLog(@"%@: [%@]", label, address.street);
                    }
                }
            }
        }
    
        else
        {
            NSLog(@"Contact access NOT granted!");
        }
    }];
    

    The above example was just based on your posted code and simply logs each contact's name, followed by each (labeled) address stored for them to the console. You can do anything you want after this, such as adding them to your own array or whatever further processing you wish.