Swift filter array using NSPredicate

Kyle Begeman picture Kyle Begeman · Sep 8, 2014 · Viewed 15.6k times · Source

I have an application written in Swift that is pulling in the users contacts from their address book.

I want to filter out the contact that only contain a company name (so that you get your "assumed" real person contact and not businesses)

Here is how this is being accomplish in the Objective-C version of my app:

NSArray *allContacts = (__bridge_transfer NSArray *)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 = [allContacts filteredArrayUsingPredicate:predicate];

This works perfectly, so here is my attempt to do this in Swift:

var contactList: NSArray = ABAddressBookCopyArrayOfAllPeople(addressBook).takeRetainedValue()

var predicate: NSPredicate = NSPredicate { (AnyObject person, NSDictionary bindings) -> Bool in
    var firstName: String = ABRecordCopyValue(person as ABRecordRef, kABPersonFirstNameProperty).takeRetainedValue() as String
    var lastName: String = ABRecordCopyValue(person as ABRecordRef, kABPersonLastNameProperty).takeRetainedValue() as String

    return firstName || lastName
})

Now this has a couple problems. I am getting these errors on the return statement and the end of the predicate call:

Error Messages

How can I provide similar functionality found in my ObjC code in Swift? Or is there a better way in swift to check if a contact has ONLY a company name and then omit it from the final array?

Thanks!

Answer

Connor picture Connor · Sep 8, 2014

If you have firstName and lastName be optional strings, you can compare them against nil and use them in a boolean expression.

Your second error is due to the extra paren after your closure. This code should work.

var predicate: NSPredicate = NSPredicate { (AnyObject person, NSDictionary bindings) -> Bool in
    var firstName: String? = ABRecordCopyValue(person as ABRecordRef, kABPersonFirstNameProperty).takeRetainedValue() as? String
    var lastName: String? = ABRecordCopyValue(person as ABRecordRef, kABPersonLastNameProperty).takeRetainedValue() as? String

    return firstName != nil || lastName != nil
}