Уведомления удаляются - PullRequest
       17

Уведомления удаляются

0 голосов
/ 25 августа 2018

У меня есть модельный объект и оконный контроллер.Я хотел бы, чтобы они могли общаться через уведомления.Я создаю оба во время метода App Delegate -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 запускает некоторые потоки для выполнения некоторых ресурсоемких вычислений в фоновом режиме.Я хотел бы, чтобы эти потоки отправляли уведомления, чтобы я мог обновлять интерфейс во время обработки.Это выглядит так:

- (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 секунд после большого вызова dispatch_async() в конце -initiateSearch: и обнаружил, что, хотя все это происходит в основном потоке пользовательского интерфейса, он также не запускает обработчик уведомлений.Если я просто позвоню postNotification::: сразу после возврата вызова dispatch_async(), он будет работать правильно, хотя.

Из этого я заключаю, что наблюдатели каким-то образом удаляются из центра уведомлений, несмотря на то, чточто мой код никогда не вызывает -removeObserver :.Почему это происходит, и как я могу или не допустить этого, или куда я могу переместить мои звонки на -addObserver, чтобы на них это не влияло?

1 Ответ

0 голосов
/ 25 августа 2018

Подозревается, что ваш оконный контроллер освобождается.

Вы назначаете его на WordSetWindowController* windowController, но эта ссылка исчезает в конце -applicationDidFinishLaunching:, и, вероятно, ваш оконный контроллер с ним.

Поскольку AppKit сохраняет само окно в открытом состоянии, в результате вы получаете экранное окно без контроллера.(Ни NSWindow, ни NSNotificationCenter не поддерживают строгие ссылки на своего контроллера / наблюдателей.)

Первоначальное уведомление работает, поскольку оно публикуется до окончания -applicationDidFinishLaunching: и / или пул авто-выпуска для этого события истощается.

Создайте сильную ссылку на ваш оконный контроллер в делегате приложения, сохраните там ссылку на оконный контроллер, и я подозреваю, что все будет работать так, как объявлено.

Что-то очень похожее случилось со мной с окномконтроллер, который также был делегатом таблицы;первоначальные сообщения о настройке и делегировании работали бы идеально, но затем более поздние события выбора загадочным образом исчезли.

...