iosabrecord

iOS get user contacts excluding businesses


I have an app that is loading all of a users contacts. I would like to exclude any business, but I can't seem to find a way to determine if a contact is a business.

I initially considered check if the "company" field contains a value when the first and last name do not, but I can't find this property from the ABRecord.

Here is how I am grabbing the first and last name:

NSString *firstName = (__bridge_transfer NSString *)ABRecordCopyValue(contactPerson, kABPersonFirstNameProperty);
NSString *lastName = (__bridge_transfer NSString *)ABRecordCopyValue(contactPerson, kABPersonLastNameProperty);

Any ideas? Thanks!


Solution

  • You can get the firm name via:

    NSString *company = (__bridge_transfer NSString *)ABRecordCopyValue(contactPerson, kABPersonOrganizationProperty);
    

    You could filter your array on the basis of whether there is an organization name, but no first name or last name.


    But, if you want to exclude businesses, you don't really care about the company name (because people may have company name, but businesses generally don't have first/last names). Just filter your records to include only those with first and/or last name:

    CFErrorRef error = NULL;
    ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
    
    if (error) {
        NSLog(@"Address book creation failure: %@", CFBridgingRelease(error));
        return;
    }
    
    ABAuthorizationStatus status = ABAddressBookGetAuthorizationStatus();
    
    if (status == kABAuthorizationStatusDenied) {
        // authorization previously denied ... tell user to go to settings and authorize access
        NSLog(@"kABAuthorizationStatusDenied");
        return;
    }
    
    ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
        if (granted) {
            NSArray *allPeople = CFBridgingRelease(ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(addressBook, NULL, kABPersonSortByLastName));
    
            // if you didn't want to sort, just use
            //
            // NSArray *allPeople = CFBridgingRelease(ABAddressBookCopyArrayOfAllPeople(addressBook));
    
            NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id person, NSDictionary *bindings) {
                NSString *firstName = CFBridgingRelease(ABRecordCopyValue((__bridge ABRecordRef)person, kABPersonFirstNameProperty));
                NSString *lastName  = CFBridgingRelease(ABRecordCopyValue((__bridge ABRecordRef)person, kABPersonLastNameProperty));
    
                return (firstName || lastName);
            }];
    
            NSArray *peopleNotCompanies = [allPeople filteredArrayUsingPredicate:predicate];
    
            // You now have an array of `ABRecordRef` associated with
            // those contacts with first or last name
        } else {
            // authorization only just now denied ... tell user to go to settings and authorize access
            NSLog(@"Access not granted: %@", CFBridgingRelease(error));
        }
    });
    

    Alternatively, you could look at the kABPersonKindProperty:

    NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id person, NSDictionary *bindings) {
        CFNumberRef recordType = ABRecordCopyValue((__bridge ABRecordRef)person, kABPersonKindProperty);
        BOOL isCompany = (recordType == kABPersonKindOrganization);
        CFRelease(recordType);
    
        return !isCompany;
    }];
    

    Whether you're comfortable relying on this kABPersonKindProperty Is up to you. I'm unsure if it's properly populated with sources like Microsft Exchange, much less whether all end-users will have always clicked the appropriate checkbox.