WillSet/DidSet 未在领域属性上调用

问题描述 投票:0回答:3

我有一个问题,因为

willSet
didSet
没有被动态领域对象调用。

代码示例:

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

Backup 类是这样定义的:

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

控制台输出为:

  • 检查:willSet:nil
  • 检查:didSet:nil
  • 检查:将添加患者
  • 检查:添加患者

虽然我宁愿期望在

will add the patient
added the patient
之间我应该得到
willSet
didSet
与患者对象。显然,病人不是零。

swift dynamic realm getter-setter
3个回答
1
投票

realm repo 中描述了一个与此相关的问题:


我建议使用没有逻辑的私有持久属性,以及具有 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"]
    }
}

这有点冗长,但为领域中的对象和独立对象提供了相同的行为。


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


0
投票

这很容易解决。只需在写入 Realm 之前更新对象属性即可。 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")
}

将打印

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

您想要哪个订单。


0
投票

2024 年更新:

该线程中的旧答案现在似乎不正确。此模式有效(在 Realm 10.49.3 上测试):

final class Foo: Object
{
    @Persisted var name: String = "" {
        didSet {
            otherName = name
        }
    }

    @Persisted var otherName: String = ""
}

如果您在写入块内设置

name
,则
didSet
会触发,并且
otherName
也会正确设置 — 即使对象已添加到 Realm 中。

(我我记得不久前在发行说明中看到过这个更改,但我现在找不到了。不过,它在测试中确实有效。)

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.