正在删除的通知
Notifications being removed
我有一个模型对象和一个 window 控制器。我希望他们能够通过通知进行交流。我在 App Delegate 的 -applicationDidFinishLaunching:
方法中创建了两者。我在加载 window 控制器的 window 之后添加观察者,如下所示:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
WordSetWindowController* windowController = [[WordSetWindowController alloc] initWithWindowNibName:@"WordSetWindowController"];
model = [[WordSetModel alloc] init];
NSWindow* window = windowController.window;
[[NSNotificationCenter defaultCenter] addObserver:windowController
selector:@selector(handleNotification:)
name:kNotification_GeneratingPairs
object:model];
[[NSNotificationCenter defaultCenter] addObserver:windowController
selector:@selector(handleNotification:)
name:kNotification_ProcessingPairs
object:model];
[[NSNotificationCenter defaultCenter] addObserver:windowController
selector:@selector(handleNotification:)
name:kNotification_UpdatePairs
object:model];
[[NSNotificationCenter defaultCenter] addObserver:windowController
selector:@selector(handleNotification:)
name:kNotification_Complete
object:model];
[model initiateSearch];
}
-iniateSearch
方法启动一些线程在后台执行一些处理器密集型计算。我希望这些线程发送通知,以便我可以在处理过程中更新 UI。它看起来像这样:
- (void)initiateSearch;
{
[[NSNotificationCenter defaultCenter] postNotificationName:kNotification_GeneratingPairs
object:self];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// ... do the first part of the calculations ...
// Notify the UI to update
self->state = SearchState_ProcessingPairs;
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:kNotification_ProcessingPairs
object:self];
});
// ... Do some more calculations ...
// Notify the UI that we're done
self->state = SearchState_Idle;
dispatch_sync(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:kNotification_Complete
object:self];
});
});
}
第一个通知正常工作,但是 dispatch_async()
调用中发生的 none 个通知曾经导致通知处理程序被调用。我试过在后台线程和 UI 线程上调用 -postNotificationName::
(通过使用 dispatch_async(dispatch_get_main_queue(),...)
和调用 -performSelectorOnMainThread:::
),但都没有任何效果。
好奇,我通过 NSTimer
添加了一个调用,它在 -initiateSearch:
结束时的大 dispatch_async()
调用之后等待 5 秒,发现即使这一切都发生在main UI 线程,它也不会触发通知处理程序。不过,如果我在 dispatch_async()
调用 returns 之后立即调用 postNotification:::
,它会正常工作。
据此,我得出结论,尽管我的代码从不调用 -removeObserver:,但观察者以某种方式从通知中心移除。为什么会发生这种情况,我怎样才能避免这种情况发生,或者我可以在哪里将我的呼叫转移到 -addObserver
以便它们不受此影响?
怀疑您的 window 控制器正在被释放。
您将其分配给 WordSetWindowController* windowController
,但该引用在 -applicationDidFinishLaunching:
的末尾消失了,很可能是您的 window 控制器。
由于 window 本身在打开时由 AppKit 保留,因此您最终会得到一个没有控制器的屏幕 window。 (NSWindow
和 NSNotificationCenter
都没有保持对其 controller/observers 的强引用。)
初始通知有效,因为它们是在 -applicationDidFinishLaunching:
结束之前发布的 and/or 该事件的自动释放池已耗尽。
在应用程序委托中创建对 window 控制器的强引用,将 window 控制器的引用存储在那里,我怀疑一切都会像宣传的那样工作。
我的 window 控制器也是 table 委托时发生了非常相似的事情;初始设置和委托消息会完美运行,但后来的选择事件神秘地消失了。
我有一个模型对象和一个 window 控制器。我希望他们能够通过通知进行交流。我在 App Delegate 的 -applicationDidFinishLaunching:
方法中创建了两者。我在加载 window 控制器的 window 之后添加观察者,如下所示:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
WordSetWindowController* windowController = [[WordSetWindowController alloc] initWithWindowNibName:@"WordSetWindowController"];
model = [[WordSetModel alloc] init];
NSWindow* window = windowController.window;
[[NSNotificationCenter defaultCenter] addObserver:windowController
selector:@selector(handleNotification:)
name:kNotification_GeneratingPairs
object:model];
[[NSNotificationCenter defaultCenter] addObserver:windowController
selector:@selector(handleNotification:)
name:kNotification_ProcessingPairs
object:model];
[[NSNotificationCenter defaultCenter] addObserver:windowController
selector:@selector(handleNotification:)
name:kNotification_UpdatePairs
object:model];
[[NSNotificationCenter defaultCenter] addObserver:windowController
selector:@selector(handleNotification:)
name:kNotification_Complete
object:model];
[model initiateSearch];
}
-iniateSearch
方法启动一些线程在后台执行一些处理器密集型计算。我希望这些线程发送通知,以便我可以在处理过程中更新 UI。它看起来像这样:
- (void)initiateSearch;
{
[[NSNotificationCenter defaultCenter] postNotificationName:kNotification_GeneratingPairs
object:self];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// ... do the first part of the calculations ...
// Notify the UI to update
self->state = SearchState_ProcessingPairs;
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:kNotification_ProcessingPairs
object:self];
});
// ... Do some more calculations ...
// Notify the UI that we're done
self->state = SearchState_Idle;
dispatch_sync(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:kNotification_Complete
object:self];
});
});
}
第一个通知正常工作,但是 dispatch_async()
调用中发生的 none 个通知曾经导致通知处理程序被调用。我试过在后台线程和 UI 线程上调用 -postNotificationName::
(通过使用 dispatch_async(dispatch_get_main_queue(),...)
和调用 -performSelectorOnMainThread:::
),但都没有任何效果。
好奇,我通过 NSTimer
添加了一个调用,它在 -initiateSearch:
结束时的大 dispatch_async()
调用之后等待 5 秒,发现即使这一切都发生在main UI 线程,它也不会触发通知处理程序。不过,如果我在 dispatch_async()
调用 returns 之后立即调用 postNotification:::
,它会正常工作。
据此,我得出结论,尽管我的代码从不调用 -removeObserver:,但观察者以某种方式从通知中心移除。为什么会发生这种情况,我怎样才能避免这种情况发生,或者我可以在哪里将我的呼叫转移到 -addObserver
以便它们不受此影响?
怀疑您的 window 控制器正在被释放。
您将其分配给 WordSetWindowController* windowController
,但该引用在 -applicationDidFinishLaunching:
的末尾消失了,很可能是您的 window 控制器。
由于 window 本身在打开时由 AppKit 保留,因此您最终会得到一个没有控制器的屏幕 window。 (NSWindow
和 NSNotificationCenter
都没有保持对其 controller/observers 的强引用。)
初始通知有效,因为它们是在 -applicationDidFinishLaunching:
结束之前发布的 and/or 该事件的自动释放池已耗尽。
在应用程序委托中创建对 window 控制器的强引用,将 window 控制器的引用存储在那里,我怀疑一切都会像宣传的那样工作。
我的 window 控制器也是 table 委托时发生了非常相似的事情;初始设置和委托消息会完美运行,但后来的选择事件神秘地消失了。