objective-cnsfilemanagernsbundle

Correct way to get Application directory path in Mac App


From my Mac OS app I was trying to get applications current directory using following code for generating a log file in the app bundle path.

NSString *path = [[[NSFileManager defaultManager] currentDirectoryPath] stringByAppendingPathComponent:@"TSPlogfile.txt"];

It worked fine when I run the application from Xcode but found [[NSFileManager defaultManager] currentDirectoryPath] returns just / while running the applicationxxx.app from finder.

Later I solved this by using [[[NSBundle mainBundle].bundlePath stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"TSPlogfile.txt"];

This works fine in both case( running app from Xcode and from finder )

Can you explain why the [[NSFileManager defaultManager] currentDirectoryPath] fails while running app from finder?


Solution

  • You should not be writing anything to the bundle or the folder where the app is located. And if your app is sandboxed, you wouldn't be able to.

    Use the "Application Support" folder instead:

    NSError *error;
    NSFileManager *manager = [NSFileManager defaultManager];
    NSURL *applicationSupport = [manager URLForDirectory:NSApplicationSupportDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:false error:&error];
    NSString *identifier = [[NSBundle mainBundle] bundleIdentifier];
    NSURL *folder = [applicationSupport URLByAppendingPathComponent:identifier];
    [manager createDirectoryAtURL:folder withIntermediateDirectories:true attributes:nil error:&error];
    NSURL *fileURL = [folder URLByAppendingPathComponent:@"TSPlogfile.txt"];
    

    I've used NSURL implementation above, but the same concept applies if using paths, too.

    See File System Programming Guide: macOS Library Directory Details.

    You ask:

    Can you explain why the [[NSFileManager defaultManager] currentDirectoryPath] fails while running app from finder?

    The folder you happen to be looking at in Finder is not the same thing as the "current directory" when the app is run. In short, the "current directory" has nothing to do with where the app is located.