I've come up with an applucation design that works better than my
previous suggestion of psuedo-polling launchedApplications. Rather,
the relaunch application subscribes to NSWorkspace's notification
center, and waits until it gaurantees that its owner-Application has
terminated. If you want the entire program plus a demo program which
uses this, go to:

http://they.dontexist.org/relaunch.zip (source is included, plus a
universal binary of the demo in action, feel free to use it all you
want)

Here is the entire code for relaunch.app:

#import <Cocoa/Cocoa.h>

@interface tizzy : NSObject {
        NSString *appPath;
}

- (void) gotQuitMessage:(NSNotification*)theNotification;

@end

#import "tizzy.h"

@implementation tizzy

// in the .nib this object must be included (though feel free to
delete the NSWindow in there)
// though im sure theres non-GUI workarounds, too

- (id) init { // create the appPath which we are waiting for to quit
        if (self = [super init]) {
                [[[NSWorkspace sharedWorkspace] notificationCenter] 
addObserver:self
selector:@selector(gotQuitMessage:)
name:NSWorkspaceDidTerminateApplicationNotification object:nil];
                appPath = [[[NSProcessInfo processInfo] arguments] 
objectAtIndex:0];
                // we are relaunching whatever application this one lies inside 
of
                // so we use a loop to get rid of everything except BigApp.app 
in this:
                // 
BigApp.app/Contents/Resources/relauncher.app/Contents/MacOS/relauncher
at least)
                int i; for (i = 0; i < 6; i++) appPath = [appPath
stringByDeletingLastPathComponent]; (
                [appPath retain];
        }
        return self;
}

// when we get the notification, relaunch the app at appPath and quit this one!
// unfortunately, i still cant figure out how to give focus to that
"parent" application.
- (void) gotQuitMessage:(NSNotification*)theNotification {
        NSString *theQuittingApp = [[theNotification userInfo]
valueForKey:@"NSApplicationPath"];
        if ([appPath isEqualToString:theQuittingApp]) {
                [[NSWorkspace sharedWorkspace] launchApplication:appPath];
                [NSApp terminate:self];
        }
}

@end



On Mon, Mar 3, 2008 at 4:22 PM, Michael Ash <[EMAIL PROTECTED]> wrote:
> On Mon, Mar 3, 2008 at 2:43 PM, Steven Degutis <[EMAIL PROTECTED]> wrote:
>  > Perhaps a small application like relaunch.app could be imbedded into
>  >  your relaunchable application, where all it pretty much does is serve
>  >  as a buffer by relaunching your application reliably (through Cocoa
>  >  methods) after your app calls it the same way you mentioned above.
>  >
>  >  [[NSWorkspace sharedWorkspace] 
> launchApplication:relauncherExecutablePath];
>  >  [NSApp terminate:self];
>  >
>  >  Then the relaunch.app program uses a method which calls itself
>  >  continuously (like a loop that wont make your app unresponsive), which
>  >  does a check to see if the original app is still running using
>  >  NSWorkspace's -launchedApplications, and only after it sees your app
>  >  end, then it will run the app again and terminate itself. This ensures
>  >  that your app opens only after it ends first. And doing this would be
>  >  quite easy, using two methods, -awakeFromNib and your custom method
>  >  -hasAppEnded. The former would launch the second one immediately, and
>  >  do nothing else, and the second one would do the check, and at the
>  >  end, if it is still running (hasnt quit and run the new app) it would
>  >  launch itself with [self performSelector:@selector(hasAppEnded)
>  >  withObject:nil afterDelay:1.0]; or something. This is what I would do
>  >  anyway. 1.0 might be too long or too short for a real application,
>  >  though.
>
>  The best way is to write a little program like this (error checking
>  removed for brevity, typed in mail client, caveat emptor):
>
>  int main(int argc, char **argv)
>  {
>     char dummy;
>     read(STDIN_FILENO, &dummy, 1);
>
>     [NSAutoreleasePool new];
>     NSURL *url = [NSURL fileURLWithPath:[NSString
>  stringWithUTF8String:argv[1]]];
>     LSOpenCFURLRef((CFURLRef)url, NULL);
>
>     return 0;
>  }
>
>  Then invoke it using an NSTask in the main app:
>
>  NSTask *task = [[NSTask alloc] init];
>  [task setLaunchPath:pathToHelper];
>  [task setArguments:[NSArray arrayWithObject:[[NSBundle mainBundle]
>  bundlePath]]];
>  [task setStandardInput:[NSPipe pipe]];
>  [task launch];
>
>  And then quit the app. The subtask will block in the read waiting for
>  data on the pipe which will never come. When your app terminates, the
>  write end of the pipe closes, unblocking the read in the subtask. The
>  subtask then relaunches your app using the URL you gave it as a
>  parameter. It's fast, easy to use, and requires no polling or messy
>  shell scripts.
>
>  Mike
>
>
> _______________________________________________
>
>  Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
>
>  Please do not post admin requests or moderator comments to the list.
>  Contact the moderators at cocoa-dev-admins(at)lists.apple.com
>
>  Help/Unsubscribe/Update your Subscription:
>  http://lists.apple.com/mailman/options/cocoa-dev/sephknows%40gmail.com
>
>  This email sent to [EMAIL PROTECTED]
>
_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]

Reply via email to