Ich habe Probleme beim Filtern von Schlüsselwortreihen (Strings) in Swift. Mein Code:
self.filteredKeywords=filter(keywords.allValues, {(keyword:NSString) ->
Bool in
let words=keyword as? NSString
return words?.containsString(searchText)
})
Da AnyObject
kein Untertyp von NSString
sein kann, bleibe ich dabei!
Swift 4.2 bietet eine neue Möglichkeit, dies zu tun:
var theBigLebowski = ["The Dude", "Angry Walter", "Maude Lebowski", "Donny Kerabatsos", "The Big Lebowski", "Little Larry Sellers"]
// after removeAll -> ["The Dude", "Angry Walter", "Donny Kerabatsos", "Little Larry Sellers"]
theBigLebowski.removeAll{ $0.contains("Lebowski")}
print(theBigLebowski)
[Aktualisiert für Swift 2.0]
Da NSString
gebührenfrei mit Swift String
verbunden ist, vermeiden Sie einfach die Zwänge mit:
3> ["abc", "bcd", "xyz"].filter() { nil != $0.rangeOfString("bc") }
$R1: [String] = 2 values {
[0] = "abc"
[1] = "bcd"
}
Aber wenn Sie denken, dass allValues
keine Zeichenketten sind:
(keywords.allValues as? [String]).filter() { nil != $0.rangeOfString("bc") }
dies gibt ein optionales Array zurück.
Ihre filter
ist über [AnyObject]
, aber Ihre Schließung dauert NSString
. Diese müssen zusammenpassen. Außerdem muss Ihr Ergebnis eine Bool
sein, kein Bool?
. Diese können Sie einfach so ansprechen:
self.filteredKeywords = filter(keywords.allValues, {
let keyword = $0 as? NSString
return keyword?.containsString(searchText) ?? false
})
Dies akzeptiert AnyObject
und versucht dann, es auf NSString
zu reduzieren. Dann wird das Ergebnis mit null (??
) verglichen, um sicherzustellen, dass es sich immer um eine Bool
handelt.
Ich würde jedoch empfehlen, keywords
als [String:String]
und nicht als NSDictionary
zu behandeln. Das würde alle Komplikationen von AnyObject
beseitigen. Dann können Sie dies einfach tun:
self.filteredKeywords = keywords.values.filter { $0.rangeOfString(searchText) != nil }
Konvertieren Sie nach Möglichkeit Foundation-Sammlungen so schnell wie möglich in Swift-Sammlungen und speichern Sie diese. Wenn Sie eingehende Foundation-Objekte haben, können Sie diese im Allgemeinen einfach mit folgenden Techniken konvertieren:
let dict = nsdict as? [String:String] ?? [:]
Oder Sie können die folgenden Schritte ausführen, um sie so zu konvertieren, dass sie beim Debuggen abstürzen (im Release jedoch unbemerkt "funktionieren"):
func failWith<T>(msg: String, value: T) -> T {
assertionFailure(msg)
return value
}
let dict = nsdict as? [String:String] ?? failWith("Couldn't convert \(d)", [:])
Es gibt sowohl ein Problem mit der GoZoner-Antwort für bestimmte Datentypen als auch einen etwas besseren Weg, dies zu tun. Die folgenden Beispiele können dies zeigen:
let animalArray: NSMutableArray = ["Dog","Cat","Otter","Deer","Rabbit"]
let filteredAnimals = animalArray.filter { $0.rangeOfString("er") != nil }
print("filteredAnimals:", filteredAnimals)
filteredAnimals: [Dog, Cat, Otter, Deer, Rabbit]
Wahrscheinlich nicht das Set, das Sie erwartet haben!
Dies funktioniert jedoch problemlos, wenn animalArray nicht als NSMutableArray eingegeben wird:
let animalArray = ["Dog","Cat","Otter","Deer","Rabbit"]
let filteredAnimals = animalArray.filter { $0.rangeOfString("er") != nil }
print("filteredAnimals:", filteredAnimals)
filteredAnimals: [Otter, Deer]
Ich würde jedoch empfehlen, $ 0.contains () anstelle von $ 0.rangeOfString ()! = Nil zu verwenden, da dies unter beiden Umständen funktioniert und die Lesbarkeit des Codes geringfügig verbessert:
let animalArray: NSMutableArray = ["Dog","Cat","Otter","Deer","Rabbit"]
let filteredAnimals = animalArray.filter { $0.contains("er") }
print("filteredAnimals:", filteredAnimals)
filteredAnimals: [Otter, Deer]