Pourquoi ça ne marche pas? Je peux utiliser array.contains () sur une chaîne, mais cela ne fonctionne pas pour un objet.
var array = ["A", "B", "C"]
array.contains("A") // True
class Dog {
var age = 1
}
var dogs = [Dog(), Dog(), Dog()]
var sparky = Dog()
dogs.contains(sparky) // Error Cannot convert value of type 'Dog' to expected argument type '@noescape (Dog) throws -> Bool
Votre Dog
doit implémenter Equatable
.
class Dog: Equatable {
var age = 1
}
func == (lhs: Dog, rhs: Dog) -> Bool {
return lhs.age == rhs.age
}
Pour vraiment expliquer ce qui se passe là-bas, nous devons d’abord comprendre qu’il existe deux méthodes contains
sur Array
(ou mieux, sur SequenceType ).
func contains(_ element: Self.Generator.Element) -> Bool
avec des contraintes
Generator.Element : Equatable
et
func contains(@noescape _ predicate: (Self.Generator.Element) throws -> Bool) rethrows -> Bool
La première recherche essentiellement un élément donné dans le tableau en utilisant ==
. La seconde utilise une fermeture qui retourne une Bool
pour rechercher des éléments.
La première méthode ne peut pas être utilisée car Dog
n'adopte pas Equatable
. Le compilateur essaie d'utiliser la deuxième méthode, mais celle-ci a une fermeture en tant que paramètre, d'où l'erreur que vous voyez.
Solution: implémentez Equatable
pour Dog
.
Si vous recherchez une comparaison de référence d'objet, vous pouvez utiliser une fermeture simple:
let result = dogs.contains({ $0 === sparky })
Rapide
Si vous n'utilisez pas d'objet, vous pouvez utiliser ce code pour contient.
let elements = [ 10, 20, 30, 40, 50]
if elements.contains(50) {
print("true")
}
Si vous utilisez NSObject Class dans Swift. Cette variable est en fonction de mes besoins. vous pouvez modifier pour votre exigence.
var cliectScreenList = [ATModelLeadInfo]()
var cliectScreenSelectedObject: ATModelLeadInfo!
Ceci est pour un même type de données.
{ $0.user_id == cliectScreenSelectedObject.user_id }
Si vous voulez tout type AnyObject.
{ "\($0.user_id)" == "\(cliectScreenSelectedObject.user_id)" }
État complet
if cliectScreenSelected.contains( { $0.user_id == cliectScreenSelectedObject.user_id } ) == false {
cliectScreenSelected.append(cliectScreenSelectedObject)
print("Object Added")
} else {
print("Object already exists")
}
Cette réponse n'est pas pertinente pour la question du PO, mais pourrait être utile pour les autres personnes confrontées au message d'erreur Swift.
Impossible d'appeler 'contient' avec une liste d'arguments de type '(any)'
Mais d’abord un petit questionnaire: pouvez-vous repérer le problème ici?
internal class FrameworkAdminConnections {
private var _localConnectionKeys = [Int]()
... other code omitted
public func isLocalConnection(_ connectionKey : Int) {
return _localConnectionKeys.contains(connectionKey)
}
}
Swift n'arrêtait pas de me dire que je ne pouvais pas invoquer contains () avec une liste d'arguments de type (Int), ce qui était un message d'erreur très inutile, et je n'ose pas admettre combien de temps il m'a fallu pour le résoudre.
Le vrai problème était que le moteur d'inférence de Swift ne parvenait pas à déterminer le résultat de la méthode includes () - car je n'aurais pas spécifié bêtement "-> Bool" dans la signature de la méthode isLocalConnection ()!