我遇到的情况是,当观察者处理传入的通知时,会删除对观察者的最后一个强引用。
这导致观察者立即被解除分配。我通常希望,当前运行的方法可以在取消分配对象之前完成。这就是正常消息发送过程中发生的情况。
代码的简化版本:
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委托。
输出结果为:
dealloc was called
returing from notification Observer
returing from notification Observer
dealloc was called
在第一种情况下,在通知处理完成之前调用dealloc。在第二种情况下,它的行为与我预期的一样。
如果我在notificationReceived
内强烈提及自我,那么dealloc只会在处理之后发生。我的期望是,ARC,运行时或其他任何人都为我保留了这个强大的参考。
我的代码出了什么问题? 或者我的期望有问题吗? 是否有Apple或Clang提供的文件?
答案 0 :(得分:3)
我的期望是,ARC,运行时或其他人保留这个 对我来说很有帮助。
情况并非如此,如Clang/ARC documentation中所述:
Objective-C方法的
self
参数变量实际上永远不会 由实施保留。它是未定义的行为,或者至少是 危险,导致在发送消息期间释放对象 那个对象。
因此,如果致电doRemoveTheOnlyStrongReferenceOfThisObserver
你可能必须使用释放self
的副作用
一个临时的强引用,以避免重新分配:
- (void)notificationRecieved:(NSNotification *)notification {
typeof(self) myself = self;
[self doRemoveTheOnlyStrongReferenceOfThisObserver];
NSLog(@"returing from notification Observer");
}
更好的解决方案可能是避免这种副作用。
答案 1 :(得分:0)
第一个dealloc可能发生在你将appDelegate的observer属性设置两次,因此第一次实例在第二次设置时就会被释放