Цель-C: Обновление FrontmostApplication

Я написал эту маленькую программу, которая должна печатать текущее переднее приложение дважды с перерывом в 3 секунды.

void printFrontmostApp() {
    NSRunningApplication *frontmostApplication = [NSWorkspace sharedWorkspace].frontmostApplication;
    NSLog(@"%@",frontmostApplication);
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        printFrontmostApp();
        sleep(3);
        printFrontmostApp();
    }
    return 0;
}

Когда я запустил эту программу, я понял, что frontmostApplication не обновляется, когда он вызывается во второй раз. Я нашел решение здесь. Но у меня все еще есть два вопроса:

1) Я хочу знать, почему приложение frontmost не обновляется.

2) Как заставить его обновляться каждый раз, когда я его называю? Я не хочу получать уведомления каждый раз, когда отключается самое переднее приложение, потому что оно немного неэффективно для моих целей.

Изменить: Просто чтобы быть кристально чистым, давайте предположим, что время сейчас 10:00:00. Я вызываю printFrontmostApp, и он печатает "Xcode" на консоли, потому что Xcode является текущим самым передним приложением. Затем программа спит в течение 3 секунд. В 10:00:01 я открыл другое приложение, скажем, TextEdit. В 10:00:03 моя программа вызывает printFrontmostApp во второй раз. Я ожидаю, что это напечатает "TextEdit", который является текущим самым передним приложением. Но вместо этого он печатает "Xcode". Я не могу понять это поведение.

Может кто-нибудь объяснить, что происходит в 10:00:03? Кажется, что функция "запоминает" значение frontmostApplication в 10:00:00 и сохраняет его при повторном вызове. Я думал, что любая память будет освобождена, когда она выйдет из области видимости, так почему же это происходит?

И как я могу получить свою программу, чтобы получить самое переднее приложение в 10:00:03? Я могу получить самое переднее приложение в 10:00:00, я должен быть в состоянии сделать то же самое через 3 секунды, верно?

2 ответа

Решение

Документация для-[NSWorkspace runningApplications] - не метод, который вы используете, но связанный - говорит:

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

От NSRunningApplication документация:

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

Это почти наверняка, что тот же принцип применяется к -frontmostApplication хотя документация не говорит об этом явно. Вы никогда не получите другие результаты при опросе, не позволив запустить цикл выполнения.

Для 1) ответ тот же, что описан в вопросе, который вы связали: вы должны соблюдать это уведомление, которое сообщает вам, когда новое приложение было активировано:

NSWorkspaceDidActivateApplicationNotification

О 2) У вас есть разные наблюдатели для активации и деактивации, такие как:

NSWorkspaceDidDeactivateApplicationNotification

Так что вы не будете наблюдать уведомления о том, что вы не зарегистрированы, пожалуйста, взгляните на NSWorkspace Notifications для получения полного списка.

В противном случае, пожалуйста, задайте свой вопрос об обновлении / опросе (который я думаю, что это не очень хорошая идея в любом случае).

Другие вопросы по тегам