Как работать с архитектурой Mac OS X Helper/Main, касающейся основных данных, общих предпочтений и уведомлений?
У меня возникли некоторые архитектурные сомнения относительно проекта (приложение Mac OS X), над которым я работаю. Он в основном состоит из двух элементов: демона, который запускается в фоновом режиме, собирает некоторые данные и средство просмотра, используемое для представления собранных данных.
Демон должен быть видимым в строке состояния (без значка док-станции) и включает в себя небольшое меню, доступное через строку состояния. Он сохраняет данные в основном хранилище данных. Одним из пунктов меню является ссылка, которая открывает просмотрщик. Когда этот просмотрщик открыт, приложение обычный GUI должно начинаться с значка док-станции и меню. Средство просмотра также открывается при открытии самого приложения (двойным щелчком по значку).
После некоторых экспериментов я понял, что лучший способ достичь этой функциональности - создать два приложения, основное приложение, представляющее просмотрщик, и вспомогательную утилиту, представляющую демон , Одной из причин, по которой я сделал это, является то, что невозможно мгновенно переключаться между значениями LSUIElement
, чтобы заставить состояние демона/зрителя.
Теперь у меня есть некоторые вопросы об этой архитектуре:
-
Оба приложения-демона и зрителя используют одно и то же хранилище данных ядра для сохранения и извлечения данных. При использовании многопоточного приложения я знаю, что для правильной синхронизации данных необходимы несколько объектов NSManagedObjectContext
. Как насчет одновременного использования нескольких приложений с одним и тем же хранилищем данных ядра? Возможно ли это даже без риска конфликтов, блокировок и т.д.? Как я могу гарантировать согласованность?
-
Демон должен всегда запускаться при запуске программы просмотра. Я достиг этого, просто перейдя через все открытые процессы и проверяя, указан ли идентификатор пучка демона. Если нет, демон запускается с помощью NSWorkspace
launchApplication
. Это прекрасно работает. Теперь, когда пользователь выходит из демона, зритель также должен остановиться. Каков наилучший способ уведомления зрителя о прекращении демона? Я могу периодически проверять активные процессы и выходить из программы просмотра, если демон демонтирован, но это звучит немного странно. Я предпочел бы выбрать какое-то уведомление, которое я отправлю, когда зритель собирается закрыть. Но поскольку это уведомление должно быть отправлено и захвачено между приложениями, я не знаю, какая услуга уведомления простая доступна. Любые мысли?
-
Приложение изолировано, поскольку оно будет распространено в Mac App Store. Запуск приложений с NSWorkspace
launchApplication
заставляет целевое приложение запускаться в той же изолированной среде, что и исходный код, который, как мне кажется, не является проблемой, потому что запуск обоих приложений в одной песочнице выглядит лучше и вероятно, есть. Но представьте себе этот сценарий: демон запускается автоматически при входе в систему (используя SMLoginItemSetEnabled
), и пользователь дважды щелкает Viewer.app. Поскольку демон уже запущен (опять же, это проверяется путем циклического перехода через активные процессы), он не будет запущен. Теперь у нас есть демон и зритель, работающий в разных песочницах? Это вызовет проблемы с настройками, хранилищем основных данных и т.д.?
-
Я хотел бы использовать NSUserDefaults
для базовой конфигурации, могу ли я каким-то образом обменять эти данные между демоном и зрителем? Опять же, оба приложения будут иметь разные идентификаторы пакетов.
Заранее благодарим за вашу помощь, оценили!
Ответы
Ответ 1
Нет ответа на эту проблему, но вот как я к этому подхожу:
Оба приложения daemon и viewer используют одно и то же хранилище данных ядра для сохранения и извлечения данных.
Поскольку совместное использование хранилища основных данных между процессами не поддерживается (насколько я знаю), у меня был бы демон демонстрацией XPC Service. Вместо открытия самого хранилища основных данных зритель будет использовать NSXPCConnection
для доступа к данным через демона.
Предполагая, что просмотрщик никогда не запускается без демона, он может использовать SMLoginItemSetEnabled
, как вы упомянули в вопросе, для регистрации службы mach для демона, а затем подключиться к этой службе.
Вот пример кода, в котором подробно описаны настройки здесь на веб-сайте Apple (резюме: демон должен быть в App.app/Contents/Library/LoginItems/daemon.bundle.id.app
), и вы также можете прочитать это сообщение в блоге, в котором обсуждаются некоторые дополнительные требования, предъявляемые песочницей (сводка: убедитесь, что ваша команда ID находится в идентификаторе пакета демона).
Демон должен всегда запускаться при запуске программы просмотра.
Весь набор: после регистрации демона с помощью SMLoginItemSetEnabled
запускает его (при необходимости), когда зритель подключается к своей службе XPC.
Теперь, когда пользователь выходит из демона, зритель также должен остановиться.
Зритель может использовать NSXPCConnection
, чтобы узнать, когда демон завершает работу. Демон может также использовать SMLoginItemSetEnabled
для самостоятельной регистрации перед тем, как он завершит работу, чтобы он не перезапускался.
Я хотел бы использовать NSUserDefaults
для базовой конфигурации, могу ли я каким-то образом обменять эти данные между демоном и зрителем? Опять же, оба приложения будут иметь разные идентификаторы пакетов.
Используйте для этого набор:
// To read or write:
NSUserDefaults* suiteDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"com.example.app.shared"];
[suiteDefaults setObject:[NSDate date] forKey:@"launchTime"];
// Add the suite to -standardUserDefaults to make reading easier:
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
[defaults addSuiteNamed:@"com.example.app.shared"];
Чтобы работать с песочницей, зритель и демон должны совместно использовать группу приложений. Вы даже можете использовать KVO для наблюдения за изменениями общих ключей.