当观察到的对象被解除分配时,cocoa绑定如何处理这种情况?
通过使用手动KVO,我必须在dealloc对象之前删除观察(removeObserver)… Cocoa绑定如何处理这个(停止观察被观察对象的dealloc)?
解决方法 2017年更新正如@Gregbrown在评论中指出的那样,2013年的原始答案在2017年不起作用.我认为原始答案确实在2013年有效,因为我的做法是不经测试就回答,但我不再使用任何代码.
那你怎么在2017年解决这个问题呢?最简单的答案是混合,有些人会发现矛盾,但不一定是在使用积木时.以下是一个快速概念验证,其中包含以下警告:
>这不是线程安全的.考虑如果两个或多个线程同时执行代码可能会发生什么.标准技术将解决这个问题.
>效率不是考虑因素!例如,您可能希望每个类调用一次dealloc,并在每个实例关联的对象中保留一个观察者/密钥路径列表.
>此代码仅支持自动删除,您无法手动选择删除观察者.你可能希望改变它.
代码:
@implementation autoRemovedKVOtypedef voID (*DealLocimp)(ID,SEL);+ (voID)forTarget:(NSObject *)target addobserver:(NSObject *)observer forKeyPath:(Nsstring *)keyPath options:(NSkeyvalueObservingOptions)options context:(nullable voID *)context{ // register the observer [target addobserver:observer forKeyPath:keyPath options:options context:context]; // swizzle dealloc to remove it Class targetClass = target.class; SEL deallocSelector = NSSelectorFromString(@"dealloc"); DealLocimp currentDealloc = (DealLocimp)method_getImplementation( class_getInstanceMethod(targetClass,deallocSelector) ); // don't capture target strongly in block or dealloc will never get called! __unsafe_unretained NSObject *targetPointer = target; voID (^replacementBlock)(ID self) = ^(__unsafe_unretained ID self) { if (self == targetPointer) [targetPointer removeObserver:observer forKeyPath:keyPath]; currentDealloc(self,deallocSelector); }; class_replaceMethod(targetClass,deallocSelector,imp_implementationWithBlock(replacementBlock),"v@:");}@end
__unsafe_unretained的两种用法都是为了解决ARC的后果.特别是方法通常保留它们的自身参数,dealloc方法不保留,并且块遵循相同的retain-as-needed模型.要使用块作为dealloc的实现,需要重写此行为,这是__unsafe_unretained正在使用的内容.
要使用上面的代码,您只需替换:
[b addobserver:a forKeyPath:keyPath options:options context:NulL];
有:
[autoRemovedKVO forTarget:b addobserver:a forKeyPath:keyPath options:options context:NulL];
考虑到上述警告,上述代码将在2017年完成工作(未来几年无法保证!)
2013年原创答案
这里概述了如何处理这种情况以及类似的情况.
首先查找关联的对象.简而言之,您可以将关联对象附加到任何其他对象(使用objc_setAssociatedobject),并指定关联对象应保留,只要它附加的对象在周围(使用OBJC_ASSOCIATION_RETAIN).
使用关联对象时,可以安排在取消分配观察对象时自动删除观察者.设X为观察者,Y为观察对象.
创建一个“取消注册”类,比如Z,它采用(通过init)一个X& Y和它的dealloc方法确实删除了Observer.
为了设置观察,X:
>创建Z的实例,传递自身和Y.
>将自己注册为Y的观察者.
>将Z与Y关联.
现在当Y被解除分配时,Z将被释放,这将导致调用Z的dealloc并取消注册X的观察.
如果你需要在Y仍处于活动状态时删除X的观察,你可以通过删除相关对象来实现这一点 – 这样做会触发它的dealloc ……
只要您想在另一个对象被释放时触发某些内容,就可以使用此模式.
HTH
总结以上是内存溢出为你收集整理的当观察对象被“释放”时,Cocoa绑定和KVO取消注册观察者全部内容,希望文章能够帮你解决当观察对象被“释放”时,Cocoa绑定和KVO取消注册观察者所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)