十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
在开发过程中,不管是出于什么需求,有的时候(自我感觉比较少)就可能会遇到监听数组元素的变化,来做一些响应的操作
抚宁网站建设公司创新互联建站,抚宁网站设计制作,有大型网站制作公司丰富经验。已为抚宁上千余家提供企业网站建设服务。企业网站搭建\成都外贸网站建设公司要多少钱,请找那个售后服务好的抚宁做网站的公司定做!
首先,iOS默认不支持对数组的KVO,因为普通方式监听的对象的地址的变化,而数组地址不变,而是里面的值发生了改变,所以我们需要做一些响应的处理,让监听数组和监听一个类的属性一样。
.m
现监听方法:
我在 AppDelegate 中监听的,故省去。
以上就可以实现了对一个数组的监听,在需要引入的地方,实现即可。
最后,数组的添加删除,就不能用一定不要用 addObject: 和 removeObject: 方法了,那样肯定会崩溃的,而要用:
这样就可以实现对数组元素的变化进行监听达到想要的效果而不崩溃。
开发中遇到这么个问题,就是给webView添加监听后,一直不走监听的方法,很是让人郁闷啊,就是下面的这个方法... 网上找了好多试了下依然没有任何起色
[self.webView.scrollView addObserver:self forKeyPath:@"contentSize" options:(NSKeyValueObservingOptionNew) context:nil];
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionaryNSKeyValueChangeKey,id *)change context:(void )context {
if ([keyPath isEqualToString:@"contentSize"]) {
CGSize fittingSize = [self.webView sizeThatFits:CGSizeZero];
self.webView.frame = CGRectMake(38, 5, kScreenWidth-38 2, fittingSize.height);
}
}
后来实在没有办法,很偶然的把webView初始化时设置的高度改成了1,然后奇迹出现了 方法开始正常走了,原来是刚开始设置的webView的高度,大于了webView内容的高度,导致kvo监听不到高度变化,那自然方法也不会走了。特此记下此坑谨防在被坑到...
经过反复研究,发现了错误的原因,并且找到解决错误的办法下面我将介绍一下我的思路:(慢慢来 跟着我的思路走)
当这个方法执行完之后,就会出现前面所展示的错误
为什么会出现这种错误呢????其实出现这种错误也很简单的:
首先在buttonAction 这个方法内,secondVC 他是一个局部变量,现在是ARC 管理,当这个方法执行完成以后,会销毁 secondVC 这个对象,那么,很自然的就会调用 SecondViewController 里面的 dealloc 这个方法【也就是第三步的方法,请看第三步】
根据错误提示,appDelegate 的属性kvoState 会被remove,但是的这个时候, it is not registered as an observer ,所以,就会出现上述的崩溃现象说了这么多,大家能理解这个崩溃的原因了吗?(PS:不懂的话也请继续了解下面的内容)
总之就是:有时候我们会忘记添加多次KVO监听或者,不小心删除如果KVO监听,如果添加多次KVO监听这个时候我们就会接受到多次监听。如果删除多次kvo程序就会造成catch既然问题的出现,那么,肯定会伴随着事务的解决
下面我讲给大家讲解几个解决的方法(百度查资料的,亲自验证,安全可靠),
那么iOS开发-黑科技防止多次添加删除KVO出现的问题
上述方法基本可以解决这个崩溃的问题,那么有没有更好的方法 解决同类 的问题呢?
对已经学会的知识,不断地总结,可以让你变得更强的。
什么情况下会调用kvo。
什么情况下不会调用kvo。
kvo的底层原理实现。
我们对name,哪些会真正的触发kvo呢
我可以告诉你,1 2 4 6会监听到kvo的变化,而其他的则检测不到。
又比如下面这个例子。
当我们对animal进行kvo监听,然后修改name的值,是否会被kvo监听到。
当我们对personclass对象重新赋值一个AnimalClass对象,是否会被kvo监听到。
我可以告诉你,第一种情况是监听不到的,第二种情况是可以监听到的。
然后,为什么呢?
我这里有两张图片。
当我们对一个对象进行kvo监听的时候,会生成一个NSKVONotifying_前缀的类,然后我们实际的操作是对这个类进行的。
通俗的讲,对对象的进行kvo监听后,这个对象的isa指针已经指向了NSKVONotifying_前缀的类,NSKVONotifying_Person。这个类是person的子类,他的superclass就是person类对象。
我们在调用setage方法的时候,会根据对象的isa找到NSKVONotifying_Person,然后在他的类里面找setage的实现。
那么有没有疑惑,setage中到底做了什么操作呢?
_NSsetIntValueAndNotify记住这个函数。
我们可以这样打印出setage的方法实现。
可以打印出
这个_NSsetIntValueAndNotify方法就是setage的实现,具体的实现,请再往后看。
Foundation框架中还有很多例如_NSSetBoolValueAndNotify、_NSSetCharValueAndNotify、_NSSetFloatValueAndNotify、_NSSetLongValueAndNotify等等函数。
继续往下看。
打印结果如下
在kvo监听下,包含了四个方法,setAge: class dealloc _isKVOA
我们先从clas来进行入手。
打印结果都是person。为什么呢?
进行kvo监听之后,不是进行变为NSKVONotifyin_Person这个类吗?怎么打印出来都是person。
其实是苹果不希望将这个NSKVONotifyin_Person暴露出来。然后在类的内部,重写了clas方法。
setAge方法的再深一层的内部实现?
我相信看完都会有所收获。
看完这些最开始的例子,我觉得会懂了。
我们来看下kvc的原理:
触发kvc的set方法才可以触发kvo机制。
所以这两种情况
KVC,即是指 NSKeyValueCoding,一个非正式的 Protocol,提供一种机制来间接访问对象的属性。KVO 就是基于 KVC 实现的关键技术之一。
键值观察通知依赖于 NSObject 的两个方法: willChangeValueForKey: 和 didChangevlueForKey: 。在一个被观察属性发生改变之前, willChangeValueForKey: 一定会被调用,这就会记录旧的值。而当改变发生后, observeValueForKey:ofObject:change:context: 和 didChangeValueForKey: 也会被调用。如果可以手动实现这些调用,就可以实现“手动触发”了。
打印顺序是:1 2 3 4。从这里看顺序似乎是 wilChangeValueForKey: 、 observeValueForKeyPath:ofObject:change:context: 、 didChangeValueForKey: 。其实,实际情况是: wilChangeValueForKey: 先调用,接着是调用 didChangeValueForKey: ,在 didChangeValueForKey: 内部调用了 observeValueForKeyPath:ofObject:change:context: 。你可以注释掉 [self didChangeValueForKey:@"now"]; 试试。
但是平时我们一般不会这么干,我们都是等系统去“自动触发”。“自动触发”的实现原理:
比如调用 setNow: 时,系统还会以某种方式在中间插入 wilChangeValueForKey: 、 didChangeValueForKey: 和 observeValueForKeyPath:ofObject:change:context: 的调用。
大致表现如下:
Apple 使用了 isa 混写(isa-swizzling)来实现 KVO,这种继承和方法注入是在运行时而不是编译时实现的。这就是正确命名如此重要的原因。只有在使用 KVC 命名约定时,KVO 才能做到这一点。KVO 在实现中通过 isa 混写(isa-swizzling)把这个对象的 isa 指针(isa 指针告诉 Runtime 系统这个对象的类是什么)指向这个新创建的子类,对象就神奇的变成了新创建的子类的实例。Apple 还重写、覆盖了 -class 方法并返回原来的类,企图欺骗我们:这个类没有变,就是原本那个类。
更多: iOS面试题合集