2014-09-07 19 views
5

Ich habe eine Anwendung in Swift geschrieben, die die Kontakte der Benutzer aus ihrem Adressbuch zieht.Swift Filter-Array mit NSPredicate

Ich möchte den Kontakt filtern, die nur einen Firmennamen enthalten (so dass Sie sich Ihre „angenommen“ reale Person Kontakt und nicht Unternehmen)

Hier ist, wie dies ist in der Objective-C-Version zu erreichen meine 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]; 

Die perfekt funktioniert, also hier ist mein Versuch, dies in Swift zu tun:

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 
}) 

Nun ist diese ein paar Probleme hat. Ich bin diese Fehler auf der return-Anweisung bekommen und das Ende des Prädikats Aufruf:

Error Messages

Wie kann ich eine ähnliche Funktionalität in meinem ObjC Code gefunden bieten in Swift? Oder gibt es einen besseren Weg, um zu überprüfen, ob ein Kontakt NUR einen Firmennamen hat und ihn dann aus dem letzten Array weglässt?

Danke!

Antwort

5

Wenn Sie vorName haben und Nachname optional Strings sein, können Sie sie gegen null vergleichen und verwende sie in einem booleschen Ausdruck.

Ihr zweiter Fehler ist aufgrund der zusätzlichen Paren nach Ihrer Schließung. Dieser Code sollte funktionieren.

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 
} 
+0

Wenn Sie NSArray anstelle von Array verwenden, können Sie diese Codezeile dann ausführen: filteredContacts lassen: NSArray = contactList.filteredArrayUsingPredicate (Prädikat) –

+0

Vielen Dank für die Klarstellung, die extra) hat mich wirklich abgewiesen, weil ich nicht bemerkt habe es! –

0

Ihr Test in der letzten Zeile in Objective-C wird zurückgegeben, wenn Vorname ist Null oder NachnameNull ist. In Ihrem schnellen Code versuchen Sie nur zwei Strings zu vergleichen, als wären sie Bools. Stattdessen möchten Sie zurückkommen, wenn vorName vorhanden ist, so sollten Sie stattdessen dies in sowohl Ihre Objective-C und Swift Code:

return firstName != nil 
+0

Scheint auch nicht zu funktionieren, löst einen anderen Fehlertyp aus. Je mehr ich mir das ansehe, desto mehr verschwende ich meine Zeit, denn Swift hat keine filteredArrayUsingPredicate: -Methode. Also muss ich wirklich jedes ABRecordRef überprüfen und sehen, ob Vor- und Nachname Null sind, während der Firmenwert nicht ist, und dann ignorieren, dass ABRecordRef –

+0

@KyleBegeman Swift Zugriff auf alle Methoden hat, auf die Sie in Objective zugreifen können. C Sie müssen nur NSArray und nicht die native Array-Klasse von Swift betrachten. Was ist der neue Fehler? – davecom

4

Wenn Sie die NSArray in einen Swift-Array konvertieren, können Sie Swift Array.filter Methode verwenden. Hier ein Beispiel mit einfacheren Objekten zur besseren Übersichtlichkeit:

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