swift中财产的财产观察员

swift中财产的财产观察员,swift,Swift,标题有点让人困惑,但它几乎说明了一切。我希望在一个属性的属性上有一个属性观察员: class A { var b: B init() { b = B() } func foo() { } } class B { var c = 0 fun bar() { } } var a = A() 在本例中,为了说明我想要什么,我希望在设置a.b.c时调用a.foo()。如果我想调用a.b.bar(),可以通过更改 va

标题有点让人困惑,但它几乎说明了一切。我希望在一个属性的属性上有一个属性观察员:

class A {

    var b: B

    init() {

        b = B()

    }

    func foo() { }

}

class B {

    var c = 0

    fun bar() { }

}

var a = A()
在本例中,为了说明我想要什么,我希望在设置
a.b.c
时调用
a.foo()
。如果我想调用
a.b.bar()
,可以通过更改

var c = 0

然而,我想做的事情并没有简单的实现方法。这是我能想到的唯一能让我随心所欲的方式:

class A {

    var b: B {
        didSet {
            b.a = self
        }
    }

    init() {

        b = B()
        b.a = self

    }

    func foo() { }

}

class B {

    weak var a: A?
    var c = 0 {
        didSet {
            a?.foo()
        }
    }

}

这似乎是一个非常混乱的解决方案,似乎应该有一个更好的解决方案。感谢您的帮助。

最干净的解决方案是使
A
NSObject
派生,这样它就可以使用键值:

class A: NSObject {
    var b: B

    override init() {
        b = B()

        super.init()
        self.addObserver(self, forKeyPath: "b.c", options: [.New], context: nil)
    }

    override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
        if keyPath == "b.c" {
            foo()
        }
    }

    func foo() {
        print("b.c. has changed")
    }
}

class B: SKSpriteNode {
    // Remember to mark it dynamic here
    dynamic var c = 0

    func bar() { }
}

var a = A()
a.b.c = 42 // will trigger a.foo()

如果这些类都是从Objective-C派生的,那么有一个简单的解决方案:您可以使用键值。在我的代码中,
a
的等价物不是从任何东西派生的,但是
B
SKSpriteNode
的一个子类。如果您想使用KVO,这是不行的。如果您想要一个简单的解决方案,那么从NSObject派生一个对象来实现这一点是值得的。令人惊讶地让人想起我说过的话。:)ObjC有自己的优势。这是一个完美的用例,这正是我所说的。
class A: NSObject {
    var b: B

    override init() {
        b = B()

        super.init()
        self.addObserver(self, forKeyPath: "b.c", options: [.New], context: nil)
    }

    override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
        if keyPath == "b.c" {
            foo()
        }
    }

    func foo() {
        print("b.c. has changed")
    }
}

class B: SKSpriteNode {
    // Remember to mark it dynamic here
    dynamic var c = 0

    func bar() { }
}

var a = A()
a.b.c = 42 // will trigger a.foo()
protocol BDelegate {
    func foo()
}

class A: BDelegate {
    var b: B

    init() {
        b = B()
        b.delegate = self
    }

    func foo() {
        print("b.c. has changed")
    }
}

class B: SKSpriteNode {
    var delegate: BDelegate?

    var c = 0 {
        didSet {                
            delegate?.foo()
        }
    }

    func bar() { }
}

var a = A()
a.b.c = 42 // will trigger a.foo()