Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 未对领域属性调用WillSet/DidSet_Swift_Dynamic_Realm_Getter Setter - Fatal编程技术网

Swift 未对领域属性调用WillSet/DidSet

Swift 未对领域属性调用WillSet/DidSet,swift,dynamic,realm,getter-setter,Swift,Dynamic,Realm,Getter Setter,我有一个问题,因为动态领域对象没有调用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

我有一个问题,因为动态领域对象没有调用
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
其中,备份类是这样定义的:

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
  • 检查:将添加患者
  • 检查:病人补充道

虽然我更希望在
之间添加患者
添加患者
,但我应该使用患者对象获得
willSet
didSet
。显然,患者不是零。

在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"]
    }
}
这有点冗长,但为领域中的对象和独立对象提供了相同的行为



来源:

这很容易修复。只需在写入领域之前更新对象属性。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

这是您想要的订单。

欢迎使用SO!只有链接的答案在这里被认为是低质量的。如果链接过时,您的答案不会给出任何信息。引用非网站资源时,请始终确保在您的答案中包含足够的信息,以便即使链接停止工作,也能对未来的读者有用。如果这是不可能的,你应该留下一个评论的链接,而不是张贴一个答案;OP希望使用willSet和didSet,但prop属性由realm管理。实际上,您可以在没有支持属性的情况下执行此操作。更重要的是,尽管问题中存在歧义,因为看起来他们试图将属性设置为非托管属性-请参阅我对问题的评论。酷。这里我要指出的唯一一点是,您不必
重写ignoredProperties
。我从
领域继承。对象
,只有
@objc dynamic var
将被视为领域属性,其他所有内容都将被忽略。也许对于
RLMObject
来说,它过去是不同的,但我想这在现代领域版本中是不可用的(我使用的是Realm/Realm cocoa 5.0)。我甚至在Realm Browser中进行了检查,以确保不会创建这样的专栏。我发布了一个答案,但现在我查看了代码,发现有问题或者我忽略了什么。在您的
领域内。编写
您正在添加一个新的空患者
领域。添加(patient())
但随后您将患者分配给sut,就像这样
sut.patient=patient
但问题是
patient
变量从何而来?换句话说,
patient
似乎是未定义的
sut.patient=patient@Jay你说得对。这是我在SOF中为简化实际解决方案而编写的伪代码,显然我在这里犯了一个错误。修正了这个声明。只有当对象刚刚创建并且没有添加到领域中时才使用它。如果之前已添加,则仍不会显示消息。很明显,什么会导致生产中的错误,例如有人编辑对象,有一个协议方法来更新它,例如,
func-didUpdate(patient:patient?
,他还设置了
backup.patient=oldValue
,因为他不知道对象是否被添加、删除或编辑,并且willSet/didSet在所有情况下都不会触发。所以我更喜欢上面引用的领域问题页面中建议的其他解决方案。此外,出于好奇,我刚刚测试了它,但它不起作用<代码>让患者=患者(id:5);尝试realm.write{print(“检查:将添加患者”);sut.patient=patient;realm.add(patient);print(“检查:添加患者”)}
@objc dynamic var patient:patient?{willSet{print(“willSet:\(String(description:newValue))”)};didSet{print(“didSet:\(String(description:patient))”)}
结果为
willSet:nil;didSet:nil;检查:将添加患者;检查:添加患者
@Vive interest。我的答案中的Will Print部分是从Xcode控制台复制粘贴的,它表明,至少对于发布的代码来说,它在被调用的函数方面起作用。在你的问题中,这些根本没有被调用。但奇怪的是,为什么newValue为零。我同意,拥有由objc领域对象支持的Swift属性是最好的解决方案,特别是对于计算值。确实很有趣。你是用Realm还是仅仅用空的操场来测试它?我想指出的是,我上面的评论也是从我的代码中复制的,我昨天改变了顺序。零是在第一行之前创建SUT时打印的。然而,在我交换patient
sut.patient=p
的地方,即使在添加到realm之前,也不会打印任何内容。在我的问题中,指纹也是这样。无论如何,我不打算继续使用这个解决方案,因为它不会在以后进行更新——正如我在第一条评论中所写的那样。很有趣,谢谢你的回答