【发布时间】:2014-01-16 15:30:57
【问题描述】:
我有一种可能发生的情况,即在观察者处理传入通知时,对观察者的最后一个强引用被删除。
这会导致观察者立即被释放。我通常希望,当前正在运行的方法可以在对象被释放之前完成。这就是正常消息发送期间发生的情况。
代码的简化版本:
TKLAppDelegate.h:
#import <UIKit/UIKit.h>
#import "TKLNotificationObserver.h"
@interface TKLAppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) TKLNotificationObserver *observer;
@end
TKLAppDelegate.m:
#import "TKLAppDelegate.h"
@implementation TKLAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Create an observer and hold a strong reference to it in a property
self.observer = [[TKLNotificationObserver alloc] init];
// During the processing of this notification the observer will remove the only strong reference
// to it and will immediatly be dealloced, before ending processing.
[[NSNotificationCenter defaultCenter] postNotificationName:@"NotificationName" object:nil];
// Create an observer and hold a strong reference to it in a property
self.observer = [[TKLNotificationObserver alloc] init];
// During the manual calling of the same method the observer will not be dealloced, because ARC still
// holds a strong reference to the message reciever.
[self.observer notificationRecieved:nil];
return YES;
}
@end
TKLNotificationObserver.m:
#import "TKLNotificationObserver.h"
#import "TKLAppDelegate.h"
@implementation TKLNotificationObserver
- (id)init {
if (self = [super init]) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationRecieved:) name:@"NotificationName" object:nil];
}
return self;
}
- (void)notificationRecieved:(NSNotification *)notification {
[self doRemoveTheOnlyStrongReferenceOfThisObserver];
NSLog(@"returing from notification Observer");
}
- (void)doRemoveTheOnlyStrongReferenceOfThisObserver {
TKLAppDelegate * delegate = [[UIApplication sharedApplication] delegate];
delegate.observer = nil;
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"NotificationName" object:nil];
NSLog(@"dealloc was called");
}
@end
这样使用 App Delegate 风格不好,只做演示,实际代码不涉及 App Delegate。
输出是:
dealloc was called
returing from notification Observer
returing from notification Observer
dealloc was called
在第一种情况下,dealloc 在通知处理完成之前被调用。在第二种情况下,它的行为符合我的预期。
如果我在notificationReceived 中保持对self 的强引用,则dealloc 仅在处理后发生。我的期望是,ARC、运行时或其他为我保留此强参考的人。
我的代码有什么问题? 还是我的期望有问题? 是否有任何 Apple 或 Clang 提供的文档?
【问题讨论】:
-
对你来说是不是很奇怪,那个对象没有引用和解除分配,但是你把它从
NSNotificationCenter中删除了?如果NSNotificationCenter持有您的TKLNotificationObserver的引用,则不应调用dealloc。 -
NSNotificationCenter 对观察者没有强引用。
标签: ios objective-c automatic-ref-counting nsnotificationcenter