避免保留循环,NSNotificationCenter?

Avoid Retain Cycles, NSNotificationCenter?

此类别方法是否允许我避免对 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

目标是让对象消亡而不必将其移除。


注意:我正在努力避免这种情况导致保留周期:

Be sure to invoke removeObserver:name:object: before notificationObserver or any object specified in addObserver:selector:name:object: is deallocated.

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

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

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

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

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:],那么我相信您确实需要担心避免由强烈保留您的观察者的块引起的保留循环。