J'ai eu des problèmes pour filtrer un tableau de mots-clés (chaînes) dans Swift, Mon code:
self.filteredKeywords=filter(keywords.allValues, {(keyword:NSString) ->
Bool in
let words=keyword as? NSString
return words?.containsString(searchText)
})
Comme AnyObject
ne peut pas être un sous-type de NSString
, je suis coincé avec ça!
Swift 4.2 offre une nouvelle façon de procéder:
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)
[Mis à jour pour Swift 2.0]
Comme NSString
est ponté sans frais vers Swift String
, il suffit d'éviter les contraintes avec:
3> ["abc", "bcd", "xyz"].filter() { nil != $0.rangeOfString("bc") }
$R1: [String] = 2 values {
[0] = "abc"
[1] = "bcd"
}
Mais si vous pensez que allValues
ne sont pas des chaînes:
(keywords.allValues as? [String]).filter() { nil != $0.rangeOfString("bc") }
qui retourne un tableau optionnel.
Votre filter
est terminé [AnyObject]
, mais votre fermeture prend NSString
. Ceux-ci doivent correspondre. De plus, votre résultat doit être une Bool
, pas un Bool?
. Vous pouvez les adresser simplement comme ceci:
self.filteredKeywords = filter(keywords.allValues, {
let keyword = $0 as? NSString
return keyword?.containsString(searchText) ?? false
})
Ceci accepte AnyObject
et essaie ensuite de le contraindre à NSString
. Il nil-coalleces (??
) ensuite le résultat pour s’assurer qu’il est toujours une Bool
.
Je recommanderais cependant de traiter keywords
comme un [String:String]
plutôt que comme un NSDictionary
. Cela éliminerait toutes les complications de AnyObject
. Ensuite, vous pouvez simplement faire ceci:
self.filteredKeywords = keywords.values.filter { $0.rangeOfString(searchText) != nil }
Dans la mesure du possible, convertissez les collections Foundation en collections Swift dès que possible et stockez-les. Si vous avez des objets Foundation entrants, vous pouvez généralement les convertir facilement avec des techniques telles que:
let dict = nsdict as? [String:String] ?? [:]
Ou vous pouvez procéder comme suit pour les convertir de manière à ce qu'ils se bloquent lors du débogage (mais silencieusement, "fonctionnent" dans la version):
func failWith<T>(msg: String, value: T) -> T {
assertionFailure(msg)
return value
}
let dict = nsdict as? [String:String] ?? failWith("Couldn't convert \(d)", [:])
La réponse de GoZoner pose un problème pour certains types de données et constitue un moyen légèrement meilleur de procéder. Les exemples suivants peuvent montrer ceci:
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]
Probablement pas le jeu que vous attendiez!
Cependant, cela fonctionne bien de cette façon si nous ne tapons pas animalArray en tant que NSMutableArray :
let animalArray = ["Dog","Cat","Otter","Deer","Rabbit"]
let filteredAnimals = animalArray.filter { $0.rangeOfString("er") != nil }
print("filteredAnimals:", filteredAnimals)
filteredAnimals: [Otter, Deer]
Cependant, je recommanderais d'utiliser $ 0.contains () au lieu de $ 0.rangeOfString ()! = Nil car il fonctionne dans les deux cas et améliore légèrement la lisibilité du code:
let animalArray: NSMutableArray = ["Dog","Cat","Otter","Deer","Rabbit"]
let filteredAnimals = animalArray.filter { $0.contains("er") }
print("filteredAnimals:", filteredAnimals)
filteredAnimals: [Otter, Deer]