Cannot convert value of type ‘Meme!’ to expected argument type ‘@noescape (Meme) throws -> Bool’

The error message is misleading. What you actually need is to provide the compiler a way to compare two Meme instances and decide upon which criteria those instances are equal.

Let’s say you want two instances having the same name property to be treated as equal.

We make the struct conform to Equatable and we also create an == operator that compares two structs by their name property:

struct Meme:Equatable {
    var name:String!
}

func ==(lhs: Meme, rhs: Meme) -> Bool {
    return lhs.name == rhs.name
}

Now we can use indexOf with a Meme instance:

let doge = Meme(name: "doge")

let lolcat = Meme(name: "lolcat")

let memes = [lolcat, doge]

if let dogeIndex = memes.indexOf(doge) {
    print(dogeIndex)  // 1
}

If you wanted to compare two instances not by their name property but by their uniqueness, then you would have to make the struct conform to Hashable and use a unique hashValue property returning an Int:

struct Meme:Hashable {
    var name:String!
    var hashValue: Int {
        return self.name.hashValue
    }
    init(name: String) {
        self.name = name
    }
}

func ==(lhs: Meme, rhs: Meme) -> Bool {
    return lhs.hashValue == rhs.hashValue
}

let doge = Meme(name: "doge")

let lolcat = Meme(name: "lolcat")

let memes = [lolcat, doge]

if let dogeIndex = memes.indexOf(doge) {
    print(dogeIndex)  // 1
}

In this example the hashValue is made from self.name, so two different instances of Meme with a same name property will be considered equal. If you don’t want that, use another source for the hash value.

Note: in Swift 3, indexOf has become index(of:), so for this example we would change memes.indexOf(doge) to memes.index(of: doge).

Leave a Comment