【问题标题】:Avoid Retain Cycles, NSNotificationCenter?避免保留周期,NSNotificationCenter?
【发布时间】:2016-04-12 19:24:12
【问题描述】:

这种类别方法是否允许我避免对NSNotificationCenter 观察者的额外保留?

#import "NSNotificationCenter+Util.h"

@implementation NSNotificationCenter (Util)

- (void)addWeakObserver:(nonnull NSObject*)observer selector:(nonnull SEL)aSelector name:(nullable NSString *)aName object:(nullable id)anObject {
    __weak NSObject *weakObserver = observer;
    [self addObserver:weakObserver selector:aSelector name:aName object:anObject];
}

@end

目标是让对象死掉而不必移除它。


注意:我试图避免这种情况导致保留周期:

一定要在之前调用removeObserver:name:object: notificationObserver 或指定的任何对象 addObserver:selector:name:object: 已被释放。

【问题讨论】:

    标签: objective-c automatic-ref-counting nsnotificationcenter


    【解决方案1】:

    NSNotificationCenter 不保留 observer,因此您不会仅使用 addObserver:selector:name:object: 创建保留循环。你不需要一个包装方法。

    关于调用removeObserver:name:object: 的警告的原因是因为NSNotificationCenter 在 OS X 10.11 (El Capitan) 和 iOS 9 之前没有使用归零弱引用。在这些版本之前的操作系统中,如果您未能删除当observer 被释放时,通知中心的observer 将继续尝试向observer 发送通知。这通常会导致崩溃或更糟。

    如果您的部署目标至少是 OS X 10.11 或 iOS 9,那么您不必担心在释放 observer 时会删除它。

    请注意,如果您使用-[NSNotificationCenter -addObserverForName:object:queue:usingBlock:],那么我相信您确实必须担心避免由于块强烈保留您的观察者而导致的保留循环。

    【讨论】:

    • 谢谢,这正是我在 Swift 操场上摸不着头脑的原因:实际上并没有发生保留!这很棒,信息量很大,再次感谢。
    【解决方案2】:

    否 - weakObserver 将是 weak,因此如果 observer 被释放,则自动 nil,但如果 addObserver:... 保留观察者,则它保留观察者。对象中没有关于先前引用持有它的方式的历史记录,控制自己行为的是引用本身。

    但是,NSNotificationCenter 不保留其观察者,观察者几乎从不保留通知中心。没有保留周期。您引用的文本或多或少说明了这一点:存储在通知中心内的指针将变得悬空,即它不主张所有权。

    您所做的也不会使引用自动存储在中心内nil

    从 iOS 9 和 OS X v10.11 开始,此行为 is already fixed。通知中心对所有可以被弱引用的对象都使用弱引用。

    【讨论】:

    • 谢谢,我没有注意到我读错了。但更重要的是,我不知道“对象中没有关于先前引用持有它的方式的历史,是引用本身控制着自己的行为。”令人着迷。
    猜你喜欢
    • 2011-04-28
    • 2011-03-29
    • 1970-01-01
    • 2018-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-16
    • 1970-01-01
    相关资源
    最近更新 更多