Using NSWorkspace with Applications
In a continuation of the Cocoa Snippets experiment, we're going to talk about the basics of NSWorkspace in several parts. First, we're going to look at how you can use this class to work with other applications.You can use NSWorkspace to get a list of running applications. For example:
NSWorkspace * ws = [NSWorkspace sharedWorkspace];
NSArray * apps = [ws launchedApplications];
NSLog (@"%@", apps);
The output would look something like this:
{
NSApplicationBundleIdentifier = "com.apple.finder";
NSApplicationName = Finder;
NSApplicationPath = "/System/Library/CoreServices/Finder.app";
NSApplicationProcessIdentifier = 184;
NSApplicationProcessSerialNumberHigh = 0;
NSApplicationProcessSerialNumberLow = 1048577;
},
{
NSApplicationBundleIdentifier = "com.macromates.textmate";
NSApplicationName = TextMate;
NSApplicationPath = "/Applications/TextMate.app";
NSApplicationProcessIdentifier = 220;
NSApplicationProcessSerialNumberHigh = 0;
NSApplicationProcessSerialNumberLow = 2490369;
},
{
NSApplicationBundleIdentifier = "com.apple.iTunes";
NSApplicationName = iTunes;
NSApplicationPath = "/Applications/iTunes.app";
NSApplicationProcessIdentifier = 242;
NSApplicationProcessSerialNumberHigh = 0;
NSApplicationProcessSerialNumberLow = 3145729;
},
The bundle identifier is set in Info.plist, and is the unique string that Launch Services needs to manage the application in the system. The process indentifier is the unix pid number. This could be used, for example, with the 'kill' command in the shell.
We can simplify and clean up this output a bit using NSArray's implementation of KVC:
NSWorkspace * ws = [NSWorkspace sharedWorkspace];
BOOL result = [ws launchApplication:@"Safari"];
NSArray * apps;
apps = [ws valueForKeyPath:@"launchedApplications.NSApplicationName"];
NSLog (@"%@", apps);
Which results in this:
(
Finder,
TextMate,
iTunes
)
We can also launch an application. The most simple way to do this is with -launchApplication:
NSWorkspace * ws = [NSWorkspace sharedWorkspace];
BOOL wasLaunched = [ws launchApplication:@"Safari"];
if ( wasLaunched )
NSLog (@"Safari was launched");
else
NSLog (@"Safari was not launched");
NSArray * apps;
apps = [ws valueForKeyPath:@"launchedApplications.NSApplicationName"];
NSLog (@"%@", apps);
Keep in mind, though, that Safari may not be actually up and running by the time you reach the next line, even if the result is "true":
MyApp[620] Safari was launched
MyApp[620] (
Finder,
TextMate,
iTunes
)
You may want to launch an application but keep your app in the foreground. This can be done with by sending a more detailed launch message:
NSWorkspace * ws = [NSWorkspace sharedWorkspace];
[ws launchAppWithBundleIdentifier: @"com.apple.Safari"
options: NSWorkspaceLaunchWithoutActivation
additionalEventParamDescriptor: NULL
launchIdentifier: nil];
Finally, you might want to get an icon for an application. This is done in two steps:
NSWorkspace * ws = [NSWorkspace sharedWorkspace];
NSString * path = [ws fullPathForApplication:@"Safari"];
NSImage * icon = [ws iconForFile: path];
NSLog (@"%@", icon);
This will give you something like the following:
NSImage 0x39b940 Size={32, 32} Reps=(
NSBitmapImageRep 0x39d5e0 Size={128, 128} ColorSpace=NSDeviceRGBColorSpace BPS=8 BPP=32 Pixels=128x128 Alpha=YES Planar=NO Format=0,
NSBitmapImageRep 0x39dd20 Size={32, 32} ColorSpace=NSDeviceRGBColorSpace BPS=8 BPP=32 Pixels=32x32 Alpha=YES Planar=NO Format=0,
NSBitmapImageRep 0x39d740 Size={16, 16} ColorSpace=NSDeviceRGBColorSpace BPS=8 BPP=32 Pixels=16x16 Alpha=YES Planar=NO Format=0
)
... which is only moderately interesting. What you'd probably want to do to display the icon is to use NSImage's -compositeToPoint:operation: to draw into a view. Alternately, you could just use an NSImageView, and use -setImage:.
There's more ground to cover with NSWorkspace beyond just dealing with applications. We'll look at that next time.
Update
By request, here's how to open a particular URL in Safari:
NSWorkspace * ws = [NSWorkspace sharedWorkspace];
NSURL * url = [NSURL URLWithString:@"http://theocacao.com/"];
[ws openURL: url];
Using NSWorkspace with Applications
Posted Oct 27, 2005 — 15 comments below
Posted Oct 27, 2005 — 15 comments below
Chuck — Oct 28, 05 467
Thank you for these Cocoa articles. I really enjoy them. Please continue.
-Chuck
David Weiss — Oct 28, 05 471
David Weiss
JB — Oct 28, 05 472
Dman — Oct 28, 05 475
can you expand the example to show how one would launch Safari with a particular URL?
Cheers.
D.
Scott Stevenson — Oct 28, 05 476
Jussi — Oct 31, 05 483
The last example does not actually open the URL in Safari, but in the "Default Web Browser"
George — Oct 31, 05 485
Jorge — Sep 09, 06 1779
Thanks!
Pir — Jun 23, 07 4437
Scott Stevenson — Jun 23, 07 4438
I'm not sure how to do that or if it even exists as API. If it exists, it might be somewhere in the CoreGraphics reference. It's also possible that you might somehow be able to do this with the Acessibility API or even AppleScript.
This would also be a good question to ask on Apple's cocoa-dev mailing list.
Nathan Gray — Dec 04, 07 5169
BufferOverflow — Aug 25, 08 6308
I wanted to know as to how i can open the Preferences of Safari from my application. Can i do it through NSWorkspace Options? Please help as i am new to Cocoa Programming.
thanks
Scott Stevenson — Aug 25, 08 6309
I don't think there's any way to do this using Cocoa alone. You might be able to do it using AppleScript.
Rune Warhuus — Feb 11, 09 6611
Please help me. I am a confused Norwegian n00b :-)
CD Rivera — Jul 18, 09 6834
I know this is an older post, but I was running into a similar problem and found an unlikely solution that worked for me. My specific issue was that Safari would close on its own immediately after the web page loaded, *unless* Safari was already opened. Here's how I solved the issue:
In Xcode, under the "Run" menu there is an option labeled "Stop on Debugger()/Debugger Str()". Try unchecking that option. It made no sense to me as [[NSWorkspace ... openUrl...] is calling the default browser (in my case, too, Safari) to do whatever it takes to access the url, independent of the app I was writing (so I thought, anyway). However, after unticking that "Stop on Debugger()..." option the problem was resolved in my case, and the "problem" web pages remained open.
Apparently, the problem is caused by web pages using Flash, which may trigger the debugging option mentioned, at least according to my source:
http://techstra.bignerdranch.com/Home
Enter page 352 and click Go, and look for the following entry:
"abraun said the following on Jul 2, 2009:"
I thought the issue described by "abraun" was unrelated, since their discussion regarded a Cocoa app that contained its own WebView. I tried the sample code for the chapter in question, and indeed confirmed the crash, and the solution. But I didn't really expected it to work for [[NSWorkspace... openUrl...] Nevertheless, I gave it a shot and it did. Give it a try.