Program directory in Objective-C (OSX) - objective-c

I'm developing an OSX-application and in it, I'd like to know what the current directory is (i.e. the directory which holds .app-file).
At the moment, I'm using the following code:
NSString *dir=[[NSFileManager defaultManager] currentDirectoryPath];
[[NSAlert alertWithMessageText:#"dir"
defaultButton:#"OK"
alternateButton:nil
otherButton:nil
informativeTextWithFormat:dir] runModal];
When running from Xcode (Run-button), this gives me the debug directory (which is what I'm looking for), but when double-clicking the app in Finder (so, in the debug directory), it's giving me / which puzzles me.
Why does this happen and how can I get the current directory reliably?

That is the bundle folder:
NSString *appPath = [[NSBundle mainBundle] bundlePath];
(reference).

When programming in Apple Swift you will get the application path with:
let pathtoapplication: String = NSBundle.mainBundle().bundlePath

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...

Cydia App Documents Folder Not Created

I have been working on a Core Data iOS app that works perfectly through Apple's "channels" – iOS simulator & Xcode installing, yet when I try to manually install it onto a device, the application crashes. My main goal is to put the app on Cydia.
A guide to preparing an app for Cydia
I read this article, and I at the bottom it said
Appstore app has a Documents folder that is created by the installation process. Jailbroken app does not. It is up to the app to create its own folder. Should you need this type of folder, you must create this with a simple mkdir command in your applicationDidFinishLaunching function. Just add a simple function: mkdir(“/var/mobile/Library/YOURAPPNAME”, 0755); If the folder already exists, no harm done. You want to do this because the install process runs as user root and the app runs as user mobile. If Cydia does this for you then the folder will have the incorrect permissions.
I do not know much about how exactly Core Data works, but I know the Core Data "database" is stored in the Documents folder, and I now believe this is the cause of the crash of my app.
The mkdir function did not work in creating a Documents folder.
How would I go about creating a Documents folder, and how would I get it to work with Core Data, ensuring the database is loaded from this folder I created?
Thanks in advance
Most likely you are still using the AppStore friendly Documents path in the methods which create and load the CoreData database file (I think Xcode will put these in your AppDelegate by default).
Check the method which loads the persistentStorageCoordinator and look for a line like this:
NSURL *storeUrl = [NSURL fileURLWithPath: [docPath stringByAppendingPathComponent:#"my_cool_app.sqlite"]];
And make sure that docPath is "/var/mobile/Library/My_Cool_App" and not originating from the standard AppStore friendly:
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docPath = [documentPaths objectAtIndex:0];
You might want to create a method which returns the proper Documents directory depending on what target you compile the app for:
+(NSString *)documentsDirectoryPath
{
#ifdef JAILBREAK
NSString *documentPath = #"/var/mobile/Library/My_Cool_App";
if (![[NSFileManager defaultManager] fileExistsAtPath:documentPath])
{
[[NSFileManager defaultManager] createDirectoryAtPath:documentPath
withIntermediateDirectories:NO
attributes:nil
error:NULL];
}
return documentPath;
#else
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
return [documentPaths objectAtIndex:0];
#endif
}

NSFileManager finds files inside a folder only when it's running under a debugger

When I run the following code under the Xcode debugger it successfully finds the package with .app extension, but when I run it standalone "file" object is nil. In fact when I did NSLogs folderEnum was also nil. Note that folderPath points to a folder that is in the same directory as the the program executable.
NSFileManager *localFileManager = [[NSFileManager alloc] init];
NSDirectoryEnumerator *folderEnum = [localFileManager enumeratorAtPath:folderPath];
NSString *file;
while (file = [folderEnum nextObject]) {
if ([[file pathExtension] isEqualToString: #"app"]) {
break;
}
}
Any ideas? Something to do with the Mac system file permissions?
Edit
I should have probably mentioned that folderPath was actually a relative path and not an absolute one. So I changed folderPath to be relative to [[NSBundle mainBundle] bundlePath] path and it works now. But if anyone can shed some light why relative path doesn't work that be great.
Does changing the first line to:
NSFileManager *localFileManager = [NSFileManager defaultManager];
make any difference? Are you just trying to get the path for your application? (There are easier ways)

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"];

Getting Current Directory in Objective C

I am trying to get current directory, but its giving me path of DEBUG folder, how i can get the path of current directory. I am using the following code.
NSFileManager *filemgr;
NSString *currentpath;
filemgr = [[NSFileManager alloc] init];
currentpath = [filemgr currentDirectoryPath];
currentDirectoryPath returns the current working directory of the program. If you launch it from Xcode in Debug mode, the current directory of the program is the Debug directory.
Developing further on that. The current working directory and launch directory may be different! Take this example, the app is launched from the home directory (~).
Library/Developer/Xcode/DerivedData/MyApp-ehwczslxjxsxiob/Build/Products/Debug/MyApp.app/Contents/MacOS/MyApp -param value
NSString *p1 = [[NSFileManager defaultManager] currentDirectoryPath];
// p1 = ~/Library/Containers/com.MyApp.beta/Data
NSString *p2 = [[NSProcessInfo processInfo] environment][#"PWD"];
// p2 = ~
Depending on the situation you might want one or the other. In my case I want to provide a CLI which takes path arguments that may be relative to the current working directory in the shell.
When getting paths for a service loaded via launchd, the paths can be very different.
NSLog(#"argv: %s", argv[0]);
NSLog(#"NSProcessInfo: %#", NSProcessInfo.processInfo.arguments[0]);
NSLog(#"currentDirectoryPath: %#", [[NSFileManager defaultManager] currentDirectoryPath]);
NSLog(#"PWD: %#", [[NSProcessInfo processInfo] environment][#"PWD"]);
Output:
argv: /Users/dev/.ioi/default-runtime-manager/default-runtime-manager
NSProcessInfo: /Users/dev/.ioi/default-runtime-manager/default-runtime-manager
currentDirectoryPath: /Users/dev/Library/Application Support/IOI/default-runtime-manager
PWD: (null)
NSProcessInfo gives the location where the executable was found.
currentDirectoryPath returns the WorkingDirectory specified in the launchd plist.
The answer to getting the executable path was found here: StackOverflow: NSProcessInfo. The other paths were from: #lupdidup