使用NSPredicate的Swiftfilter数组

我有一个用Swift编写的应用程序,它将通讯录中的用户联系人拉进来。

我想过滤掉只包含公司名称的联系人(这样您就可以获得“假定的”真人联系人而不是业务)

下面是在我的应用程序的Objective-C版本中如何完成的:

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]; 

这完美的工作,所以这里是我在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 }) 

现在这有几个问题。 我正在返回语句和谓词调用结束时收到这些错误:

错误消息

我如何提供Swift中ObjC代码中的类似function? 还是有更好的方法来迅速检查一个联系人是否只有一个公司名称,然后从最终的数组中省略它?

谢谢!

如果firstName和lastName是可选string,则可以将它们与nil进行比较,并在布尔expression式中使用它们。

您的第二个错误是由于您closures后的额外原因。 这个代码应该工作。

 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 } 

如果你把NSArray转换成Swift数组,你可以使用Swift的Array.filter方法。 这是一个简单的对象为了清晰起见的例子:

 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"] 

如果firstName是nil或者lastName是nil,那么在Objective-C最后一行的testing将会返回。 在你的swift代码中,你只是想比较两个string,就好像它们是Bools一样。 相反,如果firstName存在,你想返回,所以你应该在你的objective-c和Swift代码中这样做:

 return firstName != nil