问题
Will this category method allow me to avoid additional retains on NSNotificationCenter
observers?
#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
The goal is to have the object die without having to remove it.
Note: I'm trying to avoid this causing retain cycles:
Be sure to invoke
removeObserver:name:object:
beforenotificationObserver
or any object specified inaddObserver:selector:name:object:
is deallocated.
回答1:
No — weakObserver
will be weak
, so will automatically nil
if observer
is deallocated, but if addObserver:...
retains the observer then it retains the observer. There's no history in an object as to the ways that previous references have held it, it's the references themselves that control their own behaviour.
However, NSNotificationCenter
doesn't retain its observers, and observers almost never retain the notification centre. There is no retain cycle. The text you've quoted more or less says this: that pointers stored within the notification centre will become dangling, i.e. it is not asserting ownership.
What you've done also won't make the references stored within the centre automatically nil
.
As of iOS 9 and OS X v10.11, this behaviour is already fixed. A weak reference is used by the notification centre for all objects that can be referenced weakly.
回答2:
NSNotificationCenter
doesn't retain observer
, so you won't create a retain cycle just using addObserver:selector:name:object:
. You don't need a wrapper method for that.
The reason for the warning about calling removeObserver:name:object:
is because NSNotificationCenter
didn't use zeroing weak references until OS X 10.11 (El Capitan) and iOS 9. In operating systems prior to these versions, if you fail to remove observer
from the notification center when observer
is deallocated, then the notification center will continue trying to send notifications to observer
. This will generally cause a crash or worse.
If your deployment target is at least OS X 10.11 or iOS 9, then you don't have to worry about removing observer
when it is deallocated.
Note that if you use -[NSNotificationCenter -addObserverForName:object:queue:usingBlock:]
, then I believe you do have to worry about avoiding a retain cycle caused by the block strongly retaining your observer.
来源:https://stackoverflow.com/questions/36582279/avoid-retain-cycles-nsnotificationcenter