代码之家  ›  专栏  ›  技术社区  ›  user1118321

正在删除通知

  •  1
  • user1118321  · 技术社区  · 8 年前

    我有一个模型对象和一个窗口控制器。我希望他们能够通过通知进行沟通。我在应用程序代理的 -applicationDidFinishLaunching: 方法。我在加载窗口控制器的窗口后添加观察者,如下所示:

    - (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() 调用会导致调用通知处理程序。我试过打电话 -postNotificationName:: dispatch_async(dispatch_get_main_queue(),...) 通过打电话 -performSelectorOnMainThread::: )两者都没有任何效果。

    出于好奇,我通过 NSTimer 等了5秒钟 调度异步() 结束时呼叫 -initiateSearch: 并且发现即使所有这些都发生在主UI线程上,它也不会启动通知处理程序。如果我只是打电话 postNotification::: 紧接着 调度异步() 调用返回,但工作正常。

    由此,我得出结论,尽管我的代码从未调用-removeObserver:。为什么会发生这种事,我怎样才能不让它发生,或者我可以把我的电话转到哪里 -addObserver 所以他们不受影响?

    1 回复  |  直到 8 年前
        1
  •  2
  •   James Bucanek    8 年前

    怀疑您的窗口控制器被解除分配。

    你把它分配给 WordSetWindowController* windowController ,但该引用在结束时消失 -applicationDidFinishLaunching: ,很可能是你的窗口控制器。

    由于窗口本身在打开时由AppKit保留,因此最终会出现一个没有控制器的屏幕窗口。(两者都没有 NSWindow 也不是 NSNotificationCenter 保持对其控制器/观察员的强烈引用。)

    最初的通知有效,因为它们是在 -应用程序IDfinishLaunching: 结束和/或该事件的自动释放池已耗尽。

    在应用程序委托中创建对窗口控制器的强引用,将窗口控制器的引用存储在那里,我怀疑一切都将按广告的方式工作。

    在我身上发生了类似的事情,一个窗口控制器也是一个表委托;最初的设置和委托消息可以完美地工作,但后来选择事件神秘地消失了。