StonedStudio
StonedStudio

Reputation: 537

Comparing Objects Realm Swift

I'm trying to compare 2 Realm Objects in Swift.

// Object 1 Prints:

currentObject:  Optional(ObjectClass {
    order = 0;
    number = 010;
    temp = 903;
    state = 6;

})

// Object 2 Prints:

 lastObject:  Optional(ObjectClass {
        order = 0;
        number = 010;
        temp = 903;
        state = 6;

    })

Obviously the values are equal. But the Objects are not.

print(lastObject?.number == currentObject?.number) // Prints True
print(lastObject == currentObject) // Prints False

I tried to implement equatable in the object class. But Xcode isn't liking it due to Realm.

Redundant conformance of 'ObjectClass' to protocol 'Equatable'

How can I compare the variables of lastObject to currentObject? I imagine theres a better way than checking each object's variable against each other. But I don't know what it is.

Object Class:

import UIKit
import RealmSwift

class ObjectClass: Object {

    @objc dynamic var order = 0
    @objc dynamic var number = ""
    @objc dynamic var temp = 0
    @objc dynamic var state = 1

}

Upvotes: 0

Views: 1784

Answers (2)

rs7
rs7

Reputation: 1630

Realm objects already conform to Equatable and Hashable since they are subclasses of NSObject. The only thing you need to do is override the isEqual method:

import RealmSwift

class ObjectClass: Object {

    @objc dynamic var order = 0
    @objc dynamic var number = ""
    @objc dynamic var temp = 0
    @objc dynamic var state = 1

    override func isEqual(_ object: Any?) -> Bool {
        if let object = object as? ObjectClass {
            return self.order == object.order && self.number == object.number 
                   && self.temp == object.temp && self.state == object.state
        } else {
            return false
        }
    }
}

Upvotes: 3

Jay
Jay

Reputation: 35657

tl;dr

Change your object class to include a primary key and == will work to see if they are the same object. If they are the same object then their property variables will always be the same

class ObjectClass: Object {
    @objc dynamic var object_id = UUID().uuidString
    @objc dynamic var order = 0
    @objc dynamic var number = ""
    @objc dynamic var temp = 0
    @objc dynamic var state = 1

    override static func primaryKey() -> String? {
       return "object_id"
    }    
}

If you want to just compare the objects properties, then it's a straightforward property to property comparison (or implement isEqual and use == per the other answer)

Discussion

When comparing Realm objects we need to understand what we're comparing; are you looking too see if the objects properties have the same values or are you looking to see if they are the same objects?

If other words take a Realm object

class RealmObject: Object {
   @objc dynamic var text = ""
}

if two objects are created

let o0 = RealmObject()
o0.text = "Hello"

let o1 = RealmObject()
o1.text = "Hello"

and we compare the objects

print( o1 == o0 )

will print false because o0 and o1 are two separate objects.

Whereas if we compare a property

print( o0.text == o1.text )

would produce true because those properties are equal.

Along those same lines, after Realm 3.8 I believe you cannot test to see if two objects are the same using Equatable without a primary key. Check this out

let o0 = ObjectClass()
o0.order = 1

try! realm.write {
   realm.add(o0)
}
            
let o1 = realm.objects(ObjectClass.self).first!          
print( o1 == o0 ) //prints false  
print( o1.isSameObject(as: o0) ) //prints true

However, if we add a primary key to the ObjectClass

class ObjectClass: Object {
    @objc dynamic var object_id = UUID().uuidString
    @objc dynamic var order = 0

    override static func primaryKey() -> String? {
        return "object_id"
    }
}

and run the code again, they both print true

print( o1 == o0 ) //prints true  
print( o1.isSameObject(as: o0) ) //prints true

Upvotes: 1

Related Questions