objective-c - 通知被删除

标签 objective-c macos cocoa nsnotifications

我有一个模型对象和一个窗口 Controller 。我希望他们能够通过通知进行交流。我在应用程序委托(delegate)的 -applicationDidFinishLaunching: 方法期间创建了这两个项目。我在加载窗口 Controller 的窗口后添加观察者,如下所示:

- (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];
}

-initateSearch 方法启动一些线程,在后台执行一些处理器密集型计算。我希望这些线程发送通知,以便我可以在处理发生时更新 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() 调用中发生的所有通知都不会导致通知处理程序被调用。我尝试在后台线程和 UI 线程上调用 -postNotificationName:: (均使用 dispatch_async(dispatch_get_main_queue(),...) 并调用 -performSelectorOnMainThread:::) 都没有任何效果。

好奇,我通过 NSTimer 添加了一个调用,该调用在 -initiateSearch 末尾的大型 dispatch_async() 调用后等待 5 秒: 并发现即使所有这些都发生在主 UI 线程上,它也不会触发通知处理程序。如果我只是在 dispatch_async() 调用返回后立即调用 postNotification:::,它就可以正常工作。

据此,我得出结论,观察者以某种方式从通知中心删除,尽管我的代码从未调用 -removeObserver:。为什么会发生这种情况?如何防止这种情况发生,或者可以将调用移至 -addObserver 以便它们不受此影响?

最佳答案

怀疑您的窗口 Controller 正在被释放。

您将其分配给 WordSetWindowController* windowController,但该引用在 -applicationDidFinishLaunching: 末尾消失,并且可能您的窗口 Controller 也随之消失。

由于窗口本身在打开时由 AppKit 保留,因此您最终会得到一个没有 Controller 的屏幕窗口。 (NSWindowNSNotificationCenter 都不维护对其 Controller /观察者的强引用。)

初始通知有效,因为这些通知是在 -applicationDidFinishLaunching: 结束和/或该事件的自动释放池耗尽之前发布的。

在应用程序委托(delegate)中创建对窗口 Controller 的强引用,将窗口 Controller 的引用存储在那里,我怀疑一切都会像广告中那样工作。

我的窗口 Controller 也发生了非常类似的事情,它也是一个表委托(delegate);初始设置和委托(delegate)消息可以完美运行,但后来的选择事件神秘地消失了。

关于objective-c - 通知被删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52020063/

相关文章:

iOS 推送过渡在后退操作时显示上一 View 中的图像

objective-c - NSPasteboard 是否保留所有者对象?

iphone - iPad 问题中的 NSDateFormatter

ios - 父级 UITableViewController 在子级旋转时不呈现

ios - 在 UITabBarController 中隐藏了 UINavigationController

objective-c - cocoa 播放 mp3

macos - NS按钮边框颜色

macos - 尝试使用 tramp 访问远程文件时如何修复 "Wrong Type Argument: listp,"错误?

ios - 动画 CALayer anchorPoint

swift - 渲染不同尺寸的相同图像