Reputation: 6527
In my app I would like to open another app that is installed on the User's Mac (such as iPhoto). I am not sure what I should be looking for in the documentation. What is this called and how should I do it? Thank you
Upvotes: 20
Views: 19801
Reputation: 236305
Swift 5 or later
import Cocoa
func openPhotos() -> Bool {
if let photosApp = FileManager.default.urls(
for: .applicationDirectory,
in: .systemDomainMask
).first?.appendingPathComponent("Photos.app") {
return NSWorkspace.shared.open(photosApp)
}
return false
}
Usage:
if openPhotos() {
print(true)
}
Or using launchApplication with the app name parameter in the method:
import Cocoa
func openApp(_ named: String) -> Bool {
NSWorkspace.shared.launchApplication(named)
}
Usage:
if openApp("Photos") {
print(true)
}
Upvotes: 26
Reputation: 199
I second the answer by vookimedlo - unfortunately, I cannot yet comment (silly reputation limit) so I post this as an extra answer.
This is just one caveat, which might not affect too many: while launchApplication()
accepted a path to an executable (e.g. "MyApp.app/Contents/MacOS/MyApp"), this will result in an error (lacking privileges) with openApplication(::)
. You have to supply the path to the app bundle ("MyApp.app") instead.
Of particular interest when you try to make a helper ("launcher") to add as a login item. See the following and keep my comment in mind:
https://theswiftdev.com/2017/10/27/how-to-launch-a-macos-app-at-login/ (GREAT article by Tibor Bödecs)
BTW, as for vookimedlo's code: in my experience, you don't need to specify the OpenContext.arguments
with [path]
, you can simply pass a default NSWorkspace.OpenContext()
...
Upvotes: 3
Reputation: 1378
XCode 11 • MacOS Catalina 10.15 • Swift 5
NSWorkspace.shared.launchApplication is deprecated and starting from the MacOS 10.15 the new function NSWorkspace.shared.openApplication shall be used.
Example - open terminal application by its bundle id
guard let url = NSWorkspace.shared.urlForApplication(withBundleIdentifier: "com.apple.Terminal") else { return }
let path = "/bin"
let configuration = NSWorkspace.OpenConfiguration()
configuration.arguments = [path]
NSWorkspace.shared.openApplication(at: url,
configuration: configuration,
completionHandler: nil)
Example - open terminal application by its path
let url = NSURL(fileURLWithPath: "/System/Applications/Utilities/Terminal.app", isDirectory: true) as URL
let path = "/bin"
let configuration = NSWorkspace.OpenConfiguration()
configuration.arguments = [path]
NSWorkspace.shared.openApplication(at: url,
configuration: configuration,
completionHandler: nil)
Upvotes: 32
Reputation: 2278
There are different ways to do that. The most efficient is to use fvork and execve - see man vfork
and man execve
.
Less efficient but more flexible is to use the system
library call. What that actually does is runs a shell - like bash - then passes the string you provide, to bash. So you can set up pipelines, redirection and such.
Or you can send an Apple Event to the Finder: "Tell Finder Open iPhoto".
In the first two cases you want to launch the executable inside the bundle, that is, /Applications/iPhoto.app/Contents/MacOS/iPhoto
.
Try the above from the command line, in the Terminal:
$ /Applications/iPhoto.app/Contents/MacOS/iPhoto
You'll see the iPhoto App launch.
Upvotes: 0
Reputation: 36295
let task = NSTask.launchedTaskWithLaunchPath(<#path: String#>, arguments: <#[AnyObject]#>)
will probably do what you want
Upvotes: 3