我对我正在开发的一个项目(Mac应用程序)有一些架构上的疑问。它基本上由两个元素组成:在后台运行的收集数据的守护进程和用于表示收集的数据的查看器。
守护程序应该在状态栏中可见(没有停靠图标),并包括一个可通过状态栏访问的小菜单。它将数据保存在核心数据存储中。其中一个菜单项是链接,它将打开查看器。打开此查看器后,普通图形用户界面应用程序将开始包含停靠图标和菜单栏。打开应用程序本身时也会打开查看器(通过双击图标)。
经过一些试验,我发现实现此功能的最佳方法是创建两个应用程序,主应用程序表示查看器,辅助实用程序表示守护进程。我这样做的原因之一是不可能立即在LSUIElement
值之间切换以强制守护进程/查看器状态。
现在我有一些关于这个架构的问题:
NSManagedObjectContext
对象才能正确地同步数据。如果多个应用程序同时使用相同的核心数据存储,情况会怎样?在没有冲突、锁等风险的情况下,这是可能的吗?如何保证consistency?NSWorkspace
的launchApplication
启动该守护程序。这可以很好地工作。现在,当用户退出守护进程时,查看器也应该停止。通知查看器守护进程停止的最佳方式是什么?我可以定期检查活动进程,如果守护进程消失,则退出查看器,但这听起来有点奇怪。我宁愿选择在查看器即将关闭时发送的某种通知。但是,由于此通知应该在应用程序之间发送和捕获,我不知道哪个simple通知服务是可用的。任何thoughts?NSWorkspace
的launchApplication
启动应用程序会导致目标应用程序在与源代码相同的沙箱环境中运行,我认为这根本不是问题,因为在同一个沙箱中运行这两个应用程序感觉更好,,而且可能是这样。但是想象一下这样的场景:守护进程在登录时自动启动(使用SMLoginItemSetEnabled
),用户双击Viewer.app。由于守护进程已经在运行(同样,这是通过循环活动进程来检查的),因此不会启动它。现在我们让守护进程和查看器在不同的沙箱中运行,对吧?这会导致任何有关首选项、核心数据存储等的问题吗?NSUserDefaults
进行基本配置,我可以在守护进程和查看器之间以某种方式交换这些数据吗?同样,这两个应用程序将具有不同的捆绑包identifiers.提前感谢您的帮助,非常感谢!
发布于 2017-07-31 06:56:11
这个问题没有一个正确的答案,但以下是我将如何处理它:
守护进程和查看器应用程序都使用相同的核心数据存储来保存和检索数据。
因为不支持在进程之间共享核心数据存储(据我所知),所以我会让守护进程公开一个XPC Service。查看器将使用NSXPCConnection
通过守护进程访问数据,而不是打开核心数据存储本身。
假设查看器从不在没有守护进程的情况下运行,它可以使用SMLoginItemSetEnabled
为守护进程注册一个mach服务,然后连接到该服务。
苹果网站上的示例代码详细介绍了设置here的细节(摘要:守护进程需要位于App.app/Contents/Library/LoginItems/daemon.bundle.id.app
),您可能还想阅读讨论沙箱施加的一些额外要求的this blog post (摘要:额外确保您的团队ID位于守护进程的捆绑标识符中)。
守护进程应始终在查看器启动时启动。
所有设置:一旦您向SMLoginItemSetEnabled
注册了守护进程,当查看器连接到它的XPC服务时,launchd将启动它(如果需要)。
现在,当用户退出守护进程时,查看器也应该停止。
查看器可以使用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"];
要使用沙箱,查看器和守护程序必须共享一个App Group。您甚至可以使用KVO来观察共享密钥的更改。
https://stackoverflow.com/questions/14315048
复制相似问题