当对象在Swift中不符合kvc时的对象通信

时间:2018-02-13 16:17:42

标签: ios swift protocols key-value-observing cocoa-design-patterns

我想创建一个自定义视图,在另一个对象( UIControl的子类)上发生操作(如已更改属性)时显示该视图

我的方法是

  1. 创建一个UIControl对象可以符合的协议
  2. 创建我可以观察我的代表的自定义视图
  3. 不幸的是,它不起作用,更糟糕的是它崩溃了,因为编译器声称"它不符合kvc标准"

    贝娄,我的代码:

    protocol CustomDelegate: class where Self : UIControl {
        func respondeToControl() -> Bool
    }
    class CustomView: UIView {
        weak var delegate: CustomDelegate? {
            didSet{
                 observeIfControlIsPressed()
           }
       }
    
       func observeIfControlIsPressed(){
           if delegate != nil {
                let keypath = delegate! as! UIControl
    
                keypath.addObserver(keypath,
                                forKeyPath: "backgroundColor",
                             options: [NSKeyValueObservingOptions.new, NSKeyValueObservingOptions.old],
                context: nil)
    
            }
       }
    
       open override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
           print("background changed")
       }
    }
    

    我的问题是,我如何重新设计我的解决方案来实现它 工作?

2 个答案:

答案 0 :(得分:0)

你addObserver错了,“观察者”应该是自我没有“keypath”

试试这个:

keypath.addObserver(self, forKeyPath: "backgroundColor", options: [.new, .old], context: nil)

答案 1 :(得分:0)

您没有正确阅读错误。例如:

protocol CustomDelegate : class where Self : UIControl {
    func respondeToControl() -> Bool
}

class CustomView: UIView {
    weak var delegate: CustomDelegate? {
        didSet{
            observeIfControlIsPressed()
        }
    }

    func observeIfControlIsPressed(){
        if delegate != nil {
            let keypath = delegate! as! UIControl

            keypath.addObserver(keypath,
                                forKeyPath: "backgroundColor",
                                options: [NSKeyValueObservingOptions.new, NSKeyValueObservingOptions.old],
                                context: nil)

        }
    }

    open override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        print("background changed")
    }
}

class Foo : UIControl, CustomDelegate {
    func respondeToControl() -> Bool {
        return true
    }
}


class ViewController: UIViewController {

    let testBlock = UIView()

    override func viewDidLoad() {
        super.viewDidLoad()

        let view = CustomView()
        let button = Foo()

        view.delegate = button

        button.backgroundColor = UIColor.red
    }
}

引发异常:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '<Meh.Foo: 0x7fc977c1a0c0; baseClass = UIControl; frame = (0 0; 0 0); layer = <CALayer: 0x608000226480>>: An -observeValueForKeyPath:ofObject:change:context: message was received but not handled.
Key path: backgroundColor

这意味着Foo正在观察foo但未实现observeValueForKeyPath函数..

现在为什么?嗯..这是因为你做了:

keypath.addObserver(keypath,  //keypath is observing itself..
                    forKeyPath: "backgroundColor",
                    options: [NSKeyValueObservingOptions.new, NSKeyValueObservingOptions.old],
                    context: nil)

其中keypath是您的委托..并且正在自己添加观察者..

应该是:

keypath.addObserver(self,  //self is observing keypath..
                        forKeyPath: "backgroundColor",
                        options: [NSKeyValueObservingOptions.new, NSKeyValueObservingOptions.old],
                        context: nil)

addObserver的第一个参数需要是想要进行观察的类。

该更改将导致其打印:background changed ..不要忘记稍后删除观察者。