比较对象领域 Swift

Posted

技术标签:

【中文标题】比较对象领域 Swift【英文标题】:Comparing Objects Realm Swift 【发布时间】:2020-05-31 03:36:06 【问题描述】:

我正在尝试在 Swift 中比较 2 个领域对象。

// 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;

    )

显然这些值是相等的。但对象不是。

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

我尝试在对象类中实现 equatable。但由于 Realm,Xcode 不喜欢它。

“ObjectClass”与协议“Equatable”的冗余一致性

如何比较 lastObject 和 currentObject 的变量?我想有比检查每个对象的变量更好的方法。但我不知道它是什么。

对象类:

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


【问题讨论】:

【参考方案1】:

Realm 对象已经符合 Equatable 和 Hashable,因为它们是 NSObject 的子类。您唯一需要做的就是重写 isEqual 方法:

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

    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
        
    

【讨论】:

@stonedstudio 也许我忽略了一些东西,但这个答案与符合 Equatable 和 Hashable 有什么关系? isEqual 函数不只是将对象变量相互比较self.order == object.order,OP 在问题中已经提到了 我想有比相互检查每个对象的变量更好的方法。?没有理由重写 isEqual,因为它可以被称为 'func Pizza(_ object: Any?) -> Bool' 并获得相同的结果,并且您仍然保持原来的 isEqual 功能。 @Jay Realm 我相信这是因为 Realm 覆盖了 equatable。而且显然不关心对象的价值:***.com/a/38877533/4667835 @StonedStudio 当对象不受管理或受管理但不是每个对象之一时,它会执行此操作。不知道为什么这是公认的答案,因为这是你说你不想做的事情我想有一个比相互检查每个对象的变量更好的方法。无论如何,这不是一个糟糕的答案,但它似乎不符合问题标准。好吧,很高兴你得到了一些有用的东西:-) 嘿,Jay,我对链接的理解是,Realm equatable 仅在两者都受管理或不受管理时才有效。在检查托管对象时,它只检查两个对象是否指向内存中的同一点。但我可能是错的。 - 您的答案是更好的方法,因为它是类的覆盖,然后您可以使用 lastObject.isEqual(currentObject)。 - 我的临时解决方案是使用带有很长元组的 swift 语句。 @StonedStudio 我之前的回答不是很清楚,所以我更新了它并提供了一个更简单的解决方案,以及一些解释。请记住,这是一个 OBJECT 比较 - 如果您想比较变量,正如这个答案所回答的那样,它只是这些属性之间的直接比较。【参考方案2】:

tl;博士

更改您的对象类以包含一个主键,然后 == 将用于查看它们是否是相同的对象。如果它们是同一个对象,那么它们的属性变量将始终相同

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"
        

如果您只想比较对象的属性,那么这是一个简单的属性与属性比较。

讨论

在比较 Realm 对象时,我们需要了解我们要比较的是什么;您是否也在查看对象属性是否具有相同的值,或者您是否正在查看它们是否是相同的对象?

如果换句话取一个 Realm 对象

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

如果创建了两个对象

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

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

然后我们比较对象

print( o1 == o0 )

将打印 false,因为 o0 和 o1 是两个独立的对象。

如果我们比较一个属性

print( o0.text == o1.text )

会产生 true 因为这些属性是相等的。

按照同样的思路,在 Realm 3.8 之后,我相信您无法使用没有主键的 Equatable 来测试两个对象是否相同。看看这个

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

但是,如果我们向 ObjectClass 添加主键

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

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

再次运行代码,它们都打印为 true

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

【讨论】:

这是我尝试的第一件事,但没有成功。我创建了一个新的 ObjectClass 常量,然后将其设置为等于 Realm Object 的变量的变量。它仍然打印不相等。 @StonedStudio 查看我的示例和代码。它当然可以工作,除非你做的是不同的事情,因为它是直接从工作项目中复制和粘贴的。

以上是关于比较对象领域 Swift的主要内容,如果未能解决你的问题,请参考以下文章

比较领域对象

将 NSManagedObject 数组与另一个“对象”类型 Swift 2 的数组进行比较

将可比较的值类型 Int 应用于 Swift 4 中的 UIImage 对象

Swift 4 - SwiftyJson 比较数组并合并找到的值

Swift 比较运算和三目条件运算

Swift 比较内存地址