2016-02-16 19 views
10

Perché non funziona? Posso usare array.contains() su una stringa ma non funziona per un oggetto.Swift 2 Array Contiene oggetto?

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 

risposta

13

vostre Dog deve attuare Equatable.

class Dog: Equatable { 

    var age = 1 

} 

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

non funziona affatto –

9

Per spiegare veramente quello che sta succedendo lì, prima dobbiamo capire che ci sono due metodi su containsArray (o per meglio dire, il SequenceType).

func contains(_ element: Self.Generator.Element) -> Bool 

con vincoli

Generator.Element : Equatable 

e

func contains(@noescape _ predicate: (Self.Generator.Element) throws -> Bool) rethrows -> Bool 

La prima cerca fondamentalmente per un dato elemento dell'array utilizzando ==. Il secondo utilizza una chiusura che restituisce uno Bool per cercare elementi.

Il primo metodo non può essere utilizzato perché Dog non adotta Equatable. Il compilatore tenta di utilizzare il secondo metodo, ma quello ha una chiusura come parametro, quindi l'errore che si sta vedendo.

Soluzione: attuare Equatable per Dog.

Se siete alla ricerca per il confronto oggetto di riferimento, è possibile utilizzare una semplice chiusura:

let result = dogs.contains({ $0 === sparky }) 
+0

Grazie per la spiegazione. –

+0

Non è possibile cercare il riferimento all'oggetto? –

+0

@ user752543 Lo è, se usi una chiusura. Vedi la mia modifica. – Sulthan

2

Swift

Se non si utilizza oggetto allora si può utente questo codice per contiene.

let elements = [ 10, 20, 30, 40, 50] 

if elements.contains(50) { 

    print("true") 

} 

Se si utilizza NSObject Class in swift. Questa variabile è secondo il mio requisito. puoi modificare per il tuo requisito.

var cliectScreenList = [ATModelLeadInfo]() 
var cliectScreenSelectedObject: ATModelLeadInfo! 

Questo è per uno stesso tipo di dati.

{ $0.user_id == cliectScreenSelectedObject.user_id } 

Se si desidera il tipo AnyObject.

{ "\($0.user_id)" == "\(cliectScreenSelectedObject.user_id)" } 

Pieno

if cliectScreenSelected.contains({ $0.user_id == cliectScreenSelectedObject.user_id }) == false { 

cliectScreenSelected.append(cliectScreenSelectedObject) 

print("Object Added") 

} else { 

print("Object already exists") 

} 
0

Questa risposta non è rilevante per la domanda del PO, ma potrebbe essere utile ad altri che si confrontano con il messaggio di errore Swift

non può invocare ' contiene 'con un elenco di argomenti di tipo' (qualunque sia) '

Ma prima un rapido quiz: puoi individuare il problema qui?

internal class FrameworkAdminConnections { 

    private var _localConnectionKeys = [Int]() 

    ... other code omitted 

    public func isLocalConnection(_ connectionKey : Int) { 
     return _localConnectionKeys.contains(connectionKey) 
    } 
} 

Swift continuava a dirmi non ho potuto richiamare contiene() con una lista di argomenti di tipo (Int), che è stato un messaggio di errore molto scostante, e io non oso ammettere quanto tempo mi ha portato a finalmente capirlo.

Il vero problema era che motore di inferenza di Swift non riusciva a capire che cosa il risultato della contiene() metodo dovrebbe essere - perché avevo stupidamente non specificato "-> Bool" sul isLocalConnection) firma del metodo (!