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: In
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
.
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 :)
Class and struct are different. Struct is value type, but class is reference type.
You cannot define struct in class. On the contrary, you cannot define class in struct.
Struct and class both can conform to any protocol including your custom protocol.
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.