web-dev-qa-db-fra.com

Swift 2 Array contient l'objet?

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
10
Mitchell Hudson

Votre Dog doit implémenter Equatable.

class Dog: Equatable {

   var age = 1

}

func == (lhs: Dog, rhs: Dog) -> Bool {
      return lhs.age == rhs.age
}
13
jervine10

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

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

}
2
Anit Kumar

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 ()!

0
RenniePet