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

Posted

技术标签:

【中文标题】对象在 Swift 中不符合 kvc 时的对象通信【英文标题】:object communication when object is not kvc compliant in Swift 【发布时间】:2018-02-13 16:17:42 【问题描述】:

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

我的方法就是这样

    创建一个 UIControl 对象可以遵循的协议 创建我可以观察我的委托的自定义视图

不幸的是,它不起作用,更糟糕的是,它崩溃了,因为编译器说“它不符合 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")
   

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

【问题讨论】:

【参考方案1】:

你addObserver错了,“observer”应该是self没有“keypath”

试试这个:

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

【讨论】:

【参考方案2】:

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

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.. 不要忘记稍后删除观察者。

【讨论】:

非常感谢您花时间理解和解决我的问题! +1

以上是关于对象在 Swift 中不符合 kvc 时的对象通信的主要内容,如果未能解决你的问题,请参考以下文章

swift中构造方法和Kvc

iOS底层学习——KVC

iOS开发底层之KVC了解 - 16

iOS开发底层之KVC了解 - 16

iOS开发底层之KVC了解 - 16

加载数据后不符合 Equatable 的 Swift 对象