Swift Struct doesn't conform to protocol Equatable?

22,344

Solution 1

OK, after lots of searching, it's working...

struct MyStruct {
    var id: Int
    var value: String

    init(id: Int, value: String) {
        self.id = id
        self.value = value
    }

    var description: String {
        return "blablabla"
    }

}

extension MyStruct: Equatable {}

func ==(lhs: MyStruct, rhs: MyStruct) -> Bool {
    let areEqual = lhs.id == rhs.id &&
        lhs.value == rhs.value

    return areEqual
}

My Struct was in a class, so it didn't work.. I moved this Struct out of my class and now it's good :)

Solution 2

Swift 4.1 (and above) Updated answer:

Starting from Swift 4.1, all you have to is to conform to the Equatable protocol without the need of implementing the == method. See: SE-0185 - Synthesizing Equatable and Hashable conformance.

Example:

struct MyStruct: Equatable {
    var id: Int
    var value: String
}

let obj1 = MyStruct(id: 101, value: "object")
let obj2 = MyStruct(id: 101, value: "object")

obj1 == obj2 // true


Keep in mind that the default behavior for the == is to compare all the type properties (based on the example: lhs.id == rhs.id && lhs.value == rhs.value). If you are aiming to achieve a custom behavior (comparing only one property for instance), you have to do it by yourself:

struct MyStruct: Equatable {
    var id: Int
    var value: String
}

extension MyStruct {
    static func ==(lhs: MyStruct, rhs: MyStruct) -> Bool {
        return lhs.id == rhs.id
    }
}

let obj1 = MyStruct(id: 101, value: "obj1")
let obj2 = MyStruct(id: 101, value: "obj2")

obj1 == obj2 // true

At this point, the equality would be based on the id value, regardless of what's the value of value.

Solution 3

The issue isn't that the struct is within a class. That is certainly allowable, and there are many instances where you might want to do that. The issue is in the implementation of the Equatable protocol. You have to give a global implementation of == (which you have done), but there is no entity MyStruct....it is ParentClass.MyStruct (if the struct is defined within a parent class). The example below in itself is probably not a good example in this case, but it does show how you can do this if needed.

class ParentClass {

  struct MyStruct {
    var id: Int
    var value: String

    init(id: Int, value: String) {
      self.id = id
      self.value = value
    }

    var description: String {
      return "blablabla"
    }
  }
}

extension ParentClass.MyStruct: Equatable {}

func ==(lhs: ParentClass.MyStruct, rhs: ParentClass.MyStruct) -> Bool {
  let areEqual = lhs.id == rhs.id &&
    lhs.value == rhs.value

  return areEqual
}

let s1 = ParentClass.MyStruct(id: 1, value: "one")
let s2 = ParentClass.MyStruct(id: 2, value: "two")
let s3 = ParentClass.MyStruct(id: 1, value: "one")

s1.description    //blablabla

s1 == s2         //false
s3 == s1         //true

Note: I like to implement Comparable rather than just Equatable, which will allow you to support sorting and other functionality.

Share:
22,344

Related videos on Youtube

Insou
Author by

Insou

Updated on October 12, 2020

Comments

  • Insou
    Insou over 3 years

    How do I make a structure conform to protocol "Equatable"?

    I'm using Xcode 7.3.1

    struct MyStruct {
       var id: Int
       var value: String
    
       init(id: Int, value: String) {
           self.id = id
           self.value = value
       }
    
       var description: String {
           return "blablabla"
       }
    
    }
    

    When I use "MyStruct", Xcode shows the error:

    MyStruct does not conform to protocol "Equatable"

    Do you have an idea to make MyStruct conform to protocol?

  • Cannoliopsida
    Cannoliopsida over 6 years
    See DJohnson's answer: being in a class wasn't the issue
  • Aaron Frary
    Aaron Frary over 5 years
    This will be the right answer for most people who have this question going forward.
  • macky12345
    macky12345 about 4 years
    how to make as generic? so that I may use it in all of my class and struct