Read/Write Files to App's Bundle in Xcode

Ok so my applescript program in Xcode downloads several xml files off the internet. What I would ideally like to do is place those files in a folder called “Files” in the Resources folder of the app’s bundle. But through all of the research I have been doing I can’t see to get it to work. It looks like it might be something with objective c and the NSBundle class or something like that. Can anyone help me out with the applescript code I would need for this? All I need to do it get the POSIX path to that folder, which would also create the “Files” folder, then use the location as the destination for the xml files. Any help would be appreciated thanks in advance.

Don’t do that. You should never modify the application bundle.

Save them somewhere else, like your application’s folder in ~/Library/Application Support/ (you will have to create the folder).

Awesome! This is exactly what I was looking for I totally forgot about the application support folder. So how can I create the folder if it not there, but don’t do anything if the folder is already there? Obviously I could do some sort of implementation of if statements but I was wondering if there was a better way? I am storing the POSIX path of the location to the folder for my program in application support. Thanks.

use NSFileManager’s createDirectoryAtPath:withIntermediateDirectories:attributes:error: and it doesn’t matter. The actual folder should be named after your app’s bundle id.

Sorry but I have never really used objective C, I have been doing the majority of this in applescript. Could you give me an example of how to use that code? I am reading the documentation from apple on it but like I said I’m having trouble understanding what exactly I need to put into my program. Thanks.

It’s not Objective-C, it’s AppleScriptObjC. I don’t want to sound like a shill, but it sounds like you could do with a copy of my book.

You get the bundle ID like this:

set theBundleID to current application's NSBundle's mainBundle()'s bundleIdentifier()

Once you have built the path, you create the folder like this:

set theNSFileManager to current application's NSFileManager's defaultManager()
theNSFileManager's createDirectoryAtPath:yourPath withIntermediateDirectories:true attributes:(missing value) |error|:(missing value)

Alright here is what I have


set theBundleID to current application's NSBundle's mainBundle()'s bundleIdentifier()
        set filePath to "~/Library/Application Support/" & theBundleID
        set theNSFileManager to current application's NSFileManager's defaultManager()
        theNSFileManager's createDirectoryAtPath:(filePath as string)withIntermediateDirectories:true attributes:(missing value) |error|:(missing value)


It runs fine and continues past this but never actually creates the folder.

You can’t use paths containing ~. Use -stringByExpandingTilde() to get the full path.

So something like this?


set theBundleID to current application's NSBundle's mainBundle()'s bundleIdentifier()
        set filePath to "/Library/Application Support/" & theBundleID & "/"
        set filePath to stringByExpandingTilde(filePath)
        set theNSFileManager to current application's NSFileManager's defaultManager()
        display dialog filePath

        theNSFileManager's createDirectoryAtPath:(filePath as string)withIntermediateDirectories:true attributes:(missing value) |error|:(missing value)
        display dialog "got here!"

Not quite. That’s not how you use stringByExpandingTilde – it’s an instance message, so you need to start with an NSString and call it on that. Mind you, you seem to have lost the ~ in this post anyway, so your code is not going to work.

You’re better of not hard-coding paths like that. And build paths by adding components, not by concatenating strings – it’s less error-prone. So try something like this:

set theBundleID to current application's NSBundle's mainBundle()'s bundleIdentifier()
set appSupport to POSIX path of (path to application support)
set appSupport to current application's NSString's stringWithString:appSupport
set filePath to appSupport's stringByAppendingPathComponent:theBundleID
set theNSFileManager to current application's NSFileManager's defaultManager()
theNSFileManager's createDirectoryAtPath:filePath withIntermediateDirectories:true attributes:(missing value) |error|:(missing value)

Hmmm. It seems to have made the folder, but instead of creating the folder at ~/Library/Application Support/, it created it deep into Xcode’s app folder. Maybe because of the “current application” code? Also, I see you avoided using the tilde thing by using the applescript path to command instead, but the path of it doesn’t include the “/” at the end. Of course I could concatenate the string with “/” but like you said I probably shouldn’t do that. So how can I also append a “/” on there? Would it just be something like set filePath to filePath’s stringByAppendingPathComponent:“/”

Macintosh HD â–¸ Users â–¸ AlexKapustka â–¸ Library â–¸ Developer â–¸ Xcode â–¸ DerivedData â–¸ Show_Maker-hdggslujngeaqagulenzfdccvogx â–¸ Build â–¸ Products â–¸ Debug â–¸ ~ â–¸ Library â–¸ Application Support

No, but it should have said:

        set appSupport to POSIX path of (path to application support from user domain)

You don’t. That’s the point of using methods like stringByAppendingPathComponent: – they look after that sort of thing for you.

Really? right after I create the path if I display dialog filePath as text it comes up without the dash at the end. But thank you, from user domain fixed that issue.

POSIX paths don’t require the slash at the end.

Oh alright. I was using the variable in some shell scripts to download some xml data so I either had to add the slash at the end of the path or at the beginning of the file names of the downloaded files.

Thanks a lot though. This was pretty much the last thing I needed to get my program operational. Thanks.

or the complete Cocoa way


set theBundleID to current application's NSBundle's mainBundle()'s bundleIdentifier()
set theNSFileManager to current application's NSFileManager's defaultManager()
set appSupport to item 1 of (theNSFileManager's URLsForDirectory:(current application's NSApplicationSupportDirectory) inDomains:1)
set fileURL to appSupport's URLByAppendingPathComponent:theBundleID
theNSFileManager's createDirectoryAtURL:fileURL withIntermediateDirectories:true attributes:(missing value) |error|:(missing value)


Indeed – though that 1 instead of current application’s NSUserDomainMask is a bit down market :wink:

I got a runtime error the first time so I used the numeric constant, but maybe it was just a typo