36

say i have a very simple Person class

class Person {
    var name:String
    init(name:String) {
        self.name = name
    }
}

and i wish to store a collections of such Persons in a property, which is an array with type Person, of a People class

class People {
    var list:[Person] = []
}

perhaps i achieve this as follows

var alex = Person(name:"Alex")
var people = People()
people.list.append(alex)

QUESTION: how do i check if people.list contains the instance alex, please?

my simple attempt, which i was hoping to return true

people.list.contains(alex)

calls an error "cannot convert value of type 'Person' to expected argument type '@noescape (Person) throws -> Bool'"

ajrlewis
  • 2,968
  • 3
  • 33
  • 67

2 Answers2

53

There are two contains functions:

extension SequenceType where Generator.Element : Equatable {
    /// Return `true` iff `element` is in `self`.
    @warn_unused_result
    public func contains(element: Self.Generator.Element) -> Bool
}

extension SequenceType {
    /// Return `true` iff an element in `self` satisfies `predicate`.
    @warn_unused_result
    public func contains(@noescape predicate: (Self.Generator.Element) throws -> Bool) rethrows -> Bool
}

The compiler is complaining because the compiler knows that Person is not Equatable and thus contains needs to have a predicate but alex is not a predicate.

If the people in your array are Equatable (they aren't) then you could use:

person.list.contains(alex)

Since they aren't equatable, you could use the second contains function with:

person.list.contains { $0.name == alex.name }

or, as Martin R points out, based on 'identity' with:

person.list.contains { $0 === alex }

or you could make Person be Equatable (based on either name or identity).

GoZoner
  • 67,920
  • 20
  • 95
  • 145
  • many thanks - and to @Martin R: "theperson.list.contains { $0 === alex }" worked a charm :-) – ajrlewis Dec 30 '15 at 01:23
  • in case anyone is wondering what "$0" stands for -> https://stackoverflow.com/questions/27491620/what-does-0-represent-in-closures-in-swift – sanedroid Sep 18 '17 at 09:17
24

QUESTION: how do i check if people.list contains the instance alex, please?

class Person is a reference type, and var alex is a reference to the object storage. The identical-to operator === checks if two constants or variables refer to the same instance of a class.

Therefore, in order to check if the list contains a specific instance, use the predicate-based contains() method, and compare instances with ===:

if people.list.contains({ $0 === alex }) {
    // ...
}
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382