当观察对象被“释放”时,Cocoa绑定和KVO取消注册观察者

当观察对象被“释放”时,Cocoa绑定和KVO取消注册观察者,第1张

概述当观察对象被解除分配时,如何取消注册观察者? 当观察到的对象被解除分配时,cocoa绑定如何处理这种情况? 通过使用手动KVO,我必须在dealloc对象之前删除观察(removeObserver)… Cocoa绑定如何处理这个(停止观察被观察对象的dealloc)? 2017年更新 正如@GregBrown在评论中指出的那样,2013年的原始答案在2017年不起作用.我认为原始答案确实在2013 当观察对象被解除分配时,如何取消注册观察者?

当观察到的对象被解除分配时,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取消注册观察者所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1020412.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-23
下一篇 2022-05-23

发表评论

登录后才能评论

评论列表(0条)

保存