简体   繁体   English

未在 realm 属性上调用 WillSet/DidSet

[英]WillSet/DidSet not being invoked on realm property

I have a problem because willSet and didSet are not being called with dynamic realm object.我有一个问题,因为willSetdidSet没有被动态 realm object 调用。

Code sample:代码示例:

try! realm.write {
    sut = Backup()
    realm.add(sut) // here willSet and didSet are invoked with nil object
}

XCTAssertFalse(sut.didEditPatient) // ok
try! realm.write {
    print("CHECKING: will add the patient")
    let patient = Patient()
    realm.add(patient)
    sut.patient = patient // nothing gets printed here!
    print("CHECKING: added the patient")
}

XCTAssertTrue(sut.didEditPatient) // fails
XCTAssertNotNil(sut.patient) // ok

Where Backup class is defined this way:其中备份 class 是这样定义的:

final class Backup: Object {
    @objc dynamic var patient: Patient? {
        willSet {
            print("CHECKING: willSet: \(String(describing: newValue))")
            if newValue != patient {
                didEditPatient = true
            }
        }
        didSet { print("CHECKING: didSet: \(String(describing: patient))") }
    }
    @objc dynamic var didEditPatient: Bool = false

Output in the console is:控制台中的 Output 为:

  • CHECKING: willSet: nil检查:willSet:无
  • CHECKING: didSet: nil检查:didSet:无
  • CHECKING: will add the patient CHECKING:将添加患者
  • CHECKING: added the patient CHECKING:添加了患者

While I'd rather expect that between will add the patient and added the patient I should get willSet and didSet with patient object.虽然我更希望在will add the patientadded the patient之间我应该得到willSetdidSet与患者 object。 Obviously, patient is not nil.显然,耐心不是零。

There is one issue described about this in realm repo: realm repo 中描述了一个关于此的问题:


I would recommend using a private persisted property which has no logic, along with a non-persisted computed property which has the willSet/didSet functionality:我建议使用没有逻辑的私有持久属性,以及具有 willSet/didSet 功能的非持久计算属性:

class Model : RLMObject {
    private dynamic var backingProp = 0

    var prop : Int {
        get {
            return backingProp
        }
        set(newValue) {
            // do willSet stuff
            backingProp = newValue
            // do didSet stuff
        }
    }

    override class func ignoredProperties() -> [AnyObject]! {
        return ["prop"]
    }
}

This is a bit verbose, but gives you identical behavior for objects in a realm and standalone objects.这有点冗长,但为 realm 中的对象和独立对象提供了相同的行为。


Source: https://github.com/realm/realm-cocoa/issues/870#issuecomment-54543539来源: https://github.com/realm/realm-cocoa/issues/870#issuecomment-54543539

This is easy to fix.这很容易解决。 Just update the objects properties before writing to Realm.只需在写入 Realm 之前更新对象属性。 willSet and didSet are Swift constructs, not Objc. willSet 和 didSet 是 Swift 构造,而不是 Objc。

let p = Patient()
try! realm.write {
    print("CHECKING: will add the patient")
    sut.patient = p // moved before add to realm.
    realm.add(p)
    print("CHECKING: added the patient")
}

Will print将打印

CHECKING: will add the patient
willSet
didSet
CHECKING: added the patient

Which is the order you want.这是你想要的顺序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM