Swift3.0 KVO/KVC/通知的应用

写作初衷:看了好多关于KVC/KVO/通知的相关文章,发现都是讲理论,并且不太好理解,更不太好应用到自己的项目中。我自己总结了下它们三个,分别附了一个例子,希望对大家有所帮助~

一、KVC:Swift中使用KVC和KVO的类都必须必须继承自NSObject

iOS很多UI控件会有很多隐藏的属性,但是这些属性,我们是可以通过kvc方式用的,不会被苹果拒绝,善于使用隐藏的属性,可以提高开发效率,其实kvc也是基于runtime实现的。

查看隐藏属性的方式:

一:可以通过runtime打印出所有的隐藏属性。
二:也可以用打断点的方式,在调试区查看UI控件的隐藏属性

// 用runtime的方式打印出所有UITextView的属性
unsigned int count = 0;
    Ivar *ivars = class_copyIvarList([UITextView class], &count);
    for (int i = 0; i%s------%s", ivar_getName(ivar));
    }

kvc方式给对象的隐藏属性赋值:

        textField.placeholder = "请输入名字"
// forKey: 不支持属性的属性。最好用下面的方法:forKeyPath:
// textField.setValue(UIColor.red, forKey: "_placeholderLabel.textColor")
这句会报错:'[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key _placeholderLabel.textColor.' 
// 正确的方式:
 textField.setValue(UIColor.red, forKeyPath: "_placeholderLabel.textColor")
备注:即使是forKeyPath的方式,里面的属性也不能写一个没有的属性,否则还是会崩溃。:invalid mode 'kCFRunLoopCommonModes' provided to CFRunLoopRunSpecific - break on _CFRunLoopError_RunCalledWithInvalidMode to debug. This message will only appear once per execution.
libc++abi.dylib: terminate_handler unexpectedly threw an exception

二、KVO: 当被观察者的对象的属性被修改的时候,会通知观察者,KVC是KVO的基础
        // WKWebView监听title (webView初始化的地方监听)
        webView.addObserver(self, forKeyPath: "title", options: .new, context: nil)

     // 监听title的回调
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if (keyPath == "title") {
                self.addTitle(titleString: self.webView.title!)
        }
    }
    
    deinit { // 必须在页面销毁的时候,remove
        webView.removeObserver(self, forKeyPath: "title")
    }

三、通知:需要被观察者主动发送通知,然后观察者注册监听,比KVO多了发送通知的一步。优点是:监听不局限属性的变化,可以对多种多样的状态变化进行监听,范围广,灵活。
    // 触发通知的地方:
    [[NSNotificationCenter defaultCenter] postNotificationName:kNotificationTagDic object:dic];
    // 接收到通知的地方:
    [[[[NSNotificationCenter defaultCenter] rac_addObserverForName:kNotificationTagDic object:nil] takeUntil:[self rac_willDeallocSignal]] subscribeNext:^(id x) {
        NSDictionary *dic = [x object];
        if (dic && [dic isKindOfClass:[NSDictionary class]] && dic.count > 0) {
              
        }
    }];

你可能感兴趣的:(Swift3.0 KVO/KVC/通知的应用)