Array of Swift filters using NSPredicate

I have an application written in Swift that pulls user contacts from their address book.

I want to filter out the contact that contains only the name of the company (so that you get the "alleged" contact with a real person, not a business).

Here's how it does in the version of my Objective-C application:

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 fine, 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 of problems. I get these errors in the return statement and at 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 to quickly check if a contact has ONLY the company name and then omit it from the final array?

Thanks!

+5
source share
3 answers

If you have firstName and lastName, which are optional strings, you can compare them with nil and use them in a boolean expression.

The second error occurs due to an additional password after closing. 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 } 
+5
source

If you convert NSArray to Swift Array, you can use the Swift Array.filter method. Here is an example with simpler objects for clarity:

 let arrObjc: NSArray = ["aaa", "bab", "bbb", "baa", "cbc"] let arr: [AnyObject] = arrObjc //create a swift array with same data // filter takes a block that returns a boolean. True: keep the item, False: drop it. arr.filter{ if let s = $0 as? String { // first try to cast AnyObject to our expected type. return contains(s, "a") // return true if we want this item, false otherwise. } else { return false // this object is of the wrong type, return false. } } // returns: ["aaa", "bab", "baa"] 
+5
source

Your test on the last line in Objective-C will be returned if firstName is zero or lastName is zero. In your quick code, you are simply trying to compare two lines, as if they were Bools. Instead, you want to return if firstName exists, so instead you should do this in both Objective-C code and Swift:

 return firstName != nil 
0
source

Source: https://habr.com/ru/post/1202032/


All Articles