gpt4 book ai didi

ios - 为什么我的 NSNotificationObserver 在消息运行时被释放?

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:02:05 27 4
gpt4 key购买 nike

我有一种情况可能会发生,当观察者处理传入通知时,对观察者的最后一个强引用被删除。

这会导致立即释放观察者。我通常期望当前正在运行的方法可以在对象被释放之前完成。这就是正常消息发送期间发生的情况。

代码的简化版本:

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 提供的文档?

最佳答案

My expectation was, that ARC, the runtime or whoever else keeps this strong reference for me.

事实并非如此,如 Clang/ARC documentation 中所述:

The self parameter variable of an Objective-C method is never actually retained by the implementation. It is undefined behavior, or at least dangerous, to cause an object to be deallocated during a message send to that object.

因此,如果调用 doRemoveTheOnlyStrongReferenceOfThisObserver可以有释放 self 的副作用,你必须使用避免重新分配的临时强引用:

- (void)notificationRecieved:(NSNotification *)notification {
typeof(self) myself = self;
[self doRemoveTheOnlyStrongReferenceOfThisObserver];
NSLog(@"returing from notification Observer");
}

更好的解决方案可能会避免这种副作用。

关于ios - 为什么我的 NSNotificationObserver 在消息运行时被释放?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21166005/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com