Swift 2 Array Содержит объект?

Почему это не работает? Я могу использовать array.contains() в String, но он не работает для Object.

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

Ответ 1

Ваш Dog должен реализовать Equatable.

class Dog: Equatable {

   var age = 1

}

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

Ответ 2

Чтобы действительно объяснить, что происходит там, сначала мы должны понять, что на Array есть два метода contains (или лучше сказано, SequenceType).

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

с ограничениями

Generator.Element : Equatable

и

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

Первый в основном ищет данный элемент в массиве с помощью ==. Второй использует замыкание, которое возвращает Bool для поиска элементов.

Первый метод нельзя использовать, потому что Dog не принимает Equatable. Компилятор пытается использовать второй метод, но у него есть закрытие в качестве параметра, следовательно, ошибка, которую вы видите.

Решение: реализовать Equatable для Dog.

Если вы ищете сравнение ссылок на объекты, вы можете использовать простое закрытие:

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

Ответ 3

Свифта

Если вы не используете объект, вы можете использовать этот код для пользователя.

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

if elements.contains(50) {

    print("true")

}

Если вы используете NSObject Class в swift. Эти переменные соответствуют моим требованиям. вы можете изменить свои требования.

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

Это для одного и того же типа данных.

{ $0.user_id == cliectScreenSelectedObject.user_id }

Если вы хотите тип AnyObject.

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

Полное условие

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

cliectScreenSelected.append(cliectScreenSelectedObject)

print("Object Added")

} else {

print("Object already exists")

}

Ответ 4

Этот ответ не относится к вопросу OP, но может быть полезен другим, кто сталкивается с сообщением об ошибке Swift

Невозможно вызвать 'contains' с помощью списка аргументов типа '(что угодно)'

Но сначала быстрая опрос: можете ли вы определить проблему здесь?

internal class FrameworkAdminConnections {

   private var _localConnectionKeys = [Int]()

   ... other code omitted

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

Swift продолжал сообщать мне, что я не мог вызывать contains() с помощью списка аргументов типа (Int), что было очень бесполезным сообщением об ошибке, и я не смею признать, сколько времени мне понадобилось, чтобы, наконец, понять это,

Реальная проблема заключалась в том, что механизм вывода Swift не мог понять, какой результат метода contains() должен быть, потому что я глупо не задавал "- > Bool" на isLocalConnection()!