我可以想到几种在Mac上实现此功能的方法:
1. 命名pthread互斥量 2. 枚举运行的进程并查找匹配项 3. 创建和锁定文件
Cocoa / Carbon中是否内置了比上述选项更容易的方法?如果没有,那么在Mac上最常用的是哪三个?我会认为是2或3...
进一步阐述如何使用NSWorkspace。尝试使用NSWorkspace中的launchedApplications。它返回一个包含每个已启动应用程序的字典的NSArray。您可以循环遍历该数组,以查看是否已经运行了您要查找的应用程序。我建议您使用具有键NSApplicationBundleIdentifier的值,该值将具有类似于“com.mycompany.myapp”的值,而不是查找名称。如果您需要查找应用程序的捆绑标识符,可以查看其应用程序包中的info.plist文件。
NSWorkspace -launchedApplications
在Mac OS X 10.7中已被弃用。苹果建议您现在使用NSWorkspace -runningApplications
代替(10.6+):http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/NSWorkspace_Class/Reference/Reference.html#//apple_ref/occ/instm/NSWorkspace/runningApplications - Dave与Windows不同,Macs没有像实例那样的东西。一般来说,如果您想让应用程序运行两次,则需要复制二进制文件并双击复制版本。
如果您需要两个应用程序实例在运行,则您的思维方式不太像Mac用户: )。
编辑:从技术上讲,这是不正确的,请查看评论。
在不同操作系统之间进行映射过程管理是行不通的。或者说效果不佳。默认情况下,您只能获得一个应用程序副本。
以下是一个类似的问题,比当前问题更进一步,并且有一些回复讨论了当图像有多个副本或需要协调多个应用程序时的互锁。
关于运行时上下文的介绍,特别是关于 Mac OS X 守护程序和代理程序(以及当您确实需要运行多个可执行文件副本时,例如作为池或类似于 Apache),请参见:
applicationDidFinishLaunching
中即可。let bundleIdentifier = Bundle.main.bundleIdentifier
if NSWorkspace.shared.runningApplications.filter { $0.bundleIdentifier == bundleIdentifier }.count > 1 {
print("App already running.")
exit(0)
}
如果您使用Java Web Start(JWS)部署应用程序,则可以使用javax.jnlp.SingleInstanceService。JWS配送还将提供自动程序更新。
AppDelegate.applicationDidFinishLaunching
let runningApp =
NSWorkspace.shared.runningApplications
.filter { item in item.bundleIdentifier == Bundle.main.bundleIdentifier }
.first { item in item.processIdentifier != getpid() }
if let running = runningApp {
running.forceTerminate()
let alert = NSAlert()
alert.messageText = "App was alreday running"
alert.informativeText = "App was terminated."
alert.alertStyle = NSAlert.Style.informational
alert.addButton(withTitle: "OK")
alert.runModal()
}
注意:这假设只能有一个已经运行的应用程序。对于其他情况进行调整应该很简单。