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

317 Views Asked by At

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.

1

There are 1 best solutions below

0
On BEST ANSWER

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.