WillSet/DidSet 未在领域 属性 上调用
WillSet/DidSet not being invoked on realm property
我有一个问题,因为 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
其中备份 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
控制台中的输出是:
- 正在检查:willSet:无
- 正在检查:didSet:无
- CHECKING:将添加患者
- 正在检查:添加了患者
虽然我更希望在 will add the patient
和 added the patient
之间,但我应该得到 willSet
和 didSet
患者对象。显然,patient 不是零。
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
这很容易解决。只需在写入 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
你想要哪个顺序。
我有一个问题,因为 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
其中备份 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
控制台中的输出是:
- 正在检查:willSet:无
- 正在检查:didSet:无
- CHECKING:将添加患者
- 正在检查:添加了患者
虽然我更希望在 will add the patient
和 added the patient
之间,但我应该得到 willSet
和 didSet
患者对象。显然,patient 不是零。
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
这很容易解决。只需在写入 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
你想要哪个顺序。