How to create few apps in one bundle? - objective-c

I have an application that runs as an agent and has icon in the top bar. It should be able to run another app with window and icon in the dock. Both should to share same core data. Is there way to do it? How to open one app from another? Thank you.

Create a new cocoa application target, then add Copy Files build phase that embeds your subproject target into main app bundle:
Launch your embedded binary with NSTask class with code like this:
NSString *executablesPath = [[[NSBundle mainBundle] executablePath] stringByDeletingLastPathComponent];
NSBundle *subProjBundle = [NSBundle bundleWithPath:[executablesPath stringByAppendingPathComponent:#"subproject.app"]];
NSTask *subBinaryTask = [[NSTask alloc] init];
subBinaryTask.launchPath = [subProjBundle executablePath];
[subBinaryTask launch];

Related

Xcode: Getting the path for AppleScript file in Obj-C/Cocoa project with pathpathForResource

I have a plugin development project in X-code (10.2.1), and am trying to incorporate some AppleScript code (FatApple.applescript) into one of the methods in my implementation file.
On the AppleScript side: I have tried writing the code in Script Editor, saving to Desktop, dragging and dropping the FatApple.scptd in the "Resources", "Other Sources", etc. folders. I have tried the same steps after starting a new Xcode Project for AppleScript and dragging and dropping the FatApple.applescript file (tried with pathWithFormat type as both "scpt" and "applescript".
In Xcode I have added the FatApple.applescript to the Copy Bundle Resources, and removed from Compile Resources.
-(float) calcThing
{
NSAlert *alert=[[[NSAlert alloc] init] autorelease];
NSBundle *bundle = [NSBundle mainBundle];
NSString *path = [bundle pathForResource:#"FatApple" ofType:#"scpt"];
NSString *countstr=[NSString stringWithFormat:#"path=%#",path];
[alert setMessageText: countstr];
[alert runModal];
NSAppleScript *script = [[NSAppleScript alloc] initWithContentsOfURL:[NSURL fileURLWithPath: path] error:nil];
[script executeAndReturnError:nil];
}
I would expect to compile and run my plugin, call it in the program and receive a message with the path to my AppleScript, then ideally I could call the script and start doing stuff. Instead I receive "path=(null)".
I copied your code verbatim into a project and it worked for me, using a dummy AppleScript. The only difference I can see is that I dropped the AppleScript in the main file list rather than in the resources folder, but that shouldn't make any difference. The script shows up in the app resources folder like yours does.
The only questionable thing I see in your code is that you used NSBundle's - pathForResource:ofType: instead of - URLForResource:withExtension:. NSAppleScript wants an NSURL, so asking the bundle for a path and then converting it to a URL seems like an unnecessary step, and unnecessary steps are inherently suspicious. I can't see why that would make a difference (unless the plugin context does something funky to resource file paths), but, you know...

using SRCROOT in Xcode

I am trying to use SRCROOT path in my project like so:
// Create NSTask to interact with console
NSTask *task;
task = [[NSTask alloc] init];
// Set path to script
NSString *launch_path = #"$SRCROOT/Scripts/my_script.rb";
NSLog(launch_path);
[task setLaunchPath:launch_path];
I end up with (in log):
$SRCROOT/Scripts/my_script.rb
I want to end up to a path inside my project's directory like this:
/Application/Scripts/my_script.rb
Can anyone help me understand what I'm doing wrong? Thanks in advance.
Additionally, I've tried the following without success:
..
// Set path to script
NSString *launch_path = [NSString stringWithFormat:#"%#/Scripts/auto_checkin.rb", "$SRCROOT"];
NSLog(launch_path);
..
$SRCROOT is meaningless for runtime environment.
If you want to access the document in bundle, make sure the my_script.rb is added in the "Copy Bundle Resources", then try this:
NSString * path = [[NSBundle mainBundle] bundlePath] ;
path = [path stringByAppendingPathComponent:#"my_script.rb"] ;
$SRCROOT is path to the project file(*.xcodeproj) that defines the target. link here
The bundle term here represent Application bundle, the application bundle stores everything that the application requires for successful operation. link here

Window Constantly Wants To Be On Top Of Others - Xcode

My app has buttons that open automator workflows like this:
- (IBAction)actionname:(id)sender {
NSTaskname = [[NSTask alloc] init];
[NSTaskname setLaunchPath:#"/usr/bin/automator"];
NSArray *arguments;
arguments = [NSArray arrayWithObjects:#"/Applications/appname.app/Contents/Resources/workflowname.workflow", nil];
[NSTaskname setArguments:arguments];
[NSTaskname launch];
}
The only problem is, that every single one appears behind the window of my app. Also, one workflow launches another app which also appears behind the window.
How can I fix this?
You can probably use NSRunningApplication to bring your NSTask process to the front with its PID like this...
NSRunningApplication* app = [NSRunningApplication runningApplicationWithProcessIdentifier:[NSTaskname processIdentifier]];
[app activateWithOptions: NSApplicationActivateAllWindows];
And if you need to activate a specific application, for example your workflow that launches another app, then you could do this using the application's bundle identifier. This example will activate Safari.
NSArray* apps = [NSRunningApplication runningApplicationsWithBundleIdentifier:#"com.apple.Safari"];
[(NSRunningApplication*)[apps objectAtIndex:0] activateWithOptions: NSApplicationActivateAllWindows];

How to access pref pane bundle?

How do we access Pref Pane Bundle for Mac OS app???
I have placed images and other resources inside the pref pane bundle, but I am not able to get the path using:
NSString * path = [[NSBundle mainBundle] pathForResource:#"tick" ofType:#"png"];
where tick.png is present in the resources folder in NewPrefPane.prefPane
[NSBundle mainBundle]
returns the NSBundle for the System Preferences application since that is the one that is actually running your pane.
Use the bundle method if you just need it in your NSPreferencePane class:
[self bundle]
Use bundleForClass elsewhere in your pane code:
i.e.
NSString * path = [[NSBundle bundleForClass:[self class] pathForResource:#"tick" ofType:#"png"];

NSFileManager works when built in Xcode as release, but not when ran as standalone OS X Cocoa app

I have the following function written to randomly pick a file from a directory. It works totally fine when I build the project in Xcode for release with the application that automatically opens. However, if I open the application from finder, pressing the button that triggers this function will cause my program to freeze then crash. The only thing I could think of was changing the argument to contentsOfDirectoryAtPath: to not have the ./, but either version has the same exact issue.
Looking at Console tells me that my program exited abnormally with a Floating Point Exception, but I have no idea what's causing it. Is there something jumping out to you guys that I'm not seeing? I only started learning/using objective-C and cocoa about a week ago, so this is all fairly new to me.
Thanks for taking a look at this...
- (NSMutableString*)setFilePathRandom{
NSArray* files;
NSFileManager* fileManager;
fileManager = [[NSFileManager alloc] init];
files = [fileManager contentsOfDirectoryAtPath:#"./Random Trippy Pics" error:NULL];
NSString* directoryPath = (NSMutableString*)[fileManager currentDirectoryPath];
NSString* fileName;
do{
fileName = [files objectAtIndex:(arc4random()%[files count])];
}while([fileName isEqualToString:#".DS_Store"]);
filePath = [NSString stringWithFormat:#"%#/Random Trippy Pics/%#",directoryPath,fileName];
[fileManager release];
return filePath;
}
When an OS X application is run from Xcode, its current directory is the path to the build folder. When run "normally", the current directory is /. So your program is looking for a directory at /Random Trippy Pics, which almost certainly doesn't exist. Where is that directory normally?
Edit:
You could get the directory in which the application is currently stored with this bit of code:
NSString *currentStoragePath = [[[NSBundle mainBundle] bundlePath] stringByDeletingLastPathComponent];
However, if the Random Trippy Pics directory is required by the application, you should store it in a known location -- preferably the application's Resource directory. Then you can get the contents with:
NSArray *files = [[NSBundle mainBundle] pathsForResourceOfType:nil inDirectory:#"Random Trippy Pics"];