Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift filter array using NSPredicate

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!

like image 246
Kyle Begeman Avatar asked Sep 07 '14 23:09

Kyle Begeman


People also ask

How do I filter an array in Swift?

To filter an array in Swift: Call the Array. filter() method on an array. Pass a filtering function as an argument to the method.

What is NSPredicate in Swift?

NSPredicate is a Foundation class that specifies how data should be fetched or filtered. Its query language, which is like a cross between a SQL WHERE clause and a regular expression, provides an expressive, natural language interface to define logical conditions on which a collection is searched.

What is predicate array?

The ARRAY (or Vector) predicate performs comparisons of two arrays using logical operators. This predicate is an optional part of the optional WHERE clause of the SELECT statement.

Does filter modify the original array Swift?

When you apply a filter on an Array, the original Array is not modified. Instead, filter(isIncluded:) creates a new Array with only the elements you want.


1 Answers

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
}
like image 191
Connor Avatar answered Sep 19 '22 12:09

Connor