Cocoa Tutorial: Working With Application Resources
For most simple applications using and managing resources is handled seamlessly and you don’t ever have to intervene programatically. There are times, however, as your applications begin to mature that you need to access resources directly. Doing so is pretty straightforward, but I thought I would document it here–if for no other reason than to have it written down somewhere for the next time I need it. I hope it might be helpful to you too.
Any files that you add to your Resources directory in your xcode project are automatically added to your application build. You can verify this with the following steps:
- Build your application in xcode
- Navigate to your project build directory and locate the .app file that was created while building–usually in either <project_path>/build/Debug or <project_path>/build/Release.
- Once you’ve found the application file, Ctrl-click the file and select Show Package Contents
- In the ensuing Finder window drill down into Contents:Resources
- You will see all of your resources files for your project there.
Now the question becomes, what’s the simplest way to get access to these resources in code. Fortunately, Cocoa makes it easy.
Loading A Property List Template
I recently needed to keep a property list file handy to use as a template for saving data. As you probably know, an NSDictionary provides a way to save the dictionary data as a property list. In this case, I didn’t see any reason why I would need to build up a dictionary from scratch in code when I could instead load in a template property list and just make changes to the parts of the ensuing dictionary that needed changed. The obvious solution to me for keeping a hold of this property list file was to just store it within the resources directory inside of my application. I then just need to grab the file from the application’s main bundle and I am in business. Here is the code I used to load in the property list file.
NSString *path = [[NSBundle mainBundle] pathForResource:@"OutputTemplate" ofType:@"plist"]; NSMutableDictionary *templateDictionary = [NSMutableDictionary dictionaryWithContentsOfFile:path]; NSLog(@"Dictionary was: %@", templateDictionary);
Note: The actual file name of the file we’re loading from the main bundle is OutputTemplate.plist
Now I can simply maniupate the NSMutableDictionary, giving it the keys and values it needs. Then, later, I simply write the dictionary out to a specified output file as follows.
[templateDictionary writeToFile:outputPath atomically:YES];
You can use this technique to load any file type you like. Just add your file that you want to your Resources directory and you’ll be good to go. To be sure, this is simply what seemed to be the best way to handle this problem to me. If you are aware of some other method that is considered a best practice, let me know. I’m always looking for a better way to do things.
Per bbum’s suggestion, this is now filed under radar: 5972712
Let’s say you’ve got some global constants that you want to define in a plist rather than in code. (The constants might contain non-ASCII characters, for example.) Where would you put the code that reads the plist and sets the constants? I’m guessing that the +initialize method of the app delegate is the best place. What’s your advice?
-applicationDidFinishLaunching or -awakeFromNib is where I would suggest.
i have doing document based application .. i have to load a window called template window inital after user select one template i have to load document window….
i done this my loading template window in applicationWillFinishLaunching after saving when user double click on app it must load document window…. but it loading template window how to avoid that…..