Using NSBundle to load my resources - objective-c

I wanted to separate my resources, nib files and localization files into a common reusable bundle. And so I created a bundle for my ios application and specified resources to be included inside the bundle using build phases, copy bundle resources. But, now if I try to load the bundle, I am not able to load the bundle. I try using [NSBundle allBundles] and the array shows only the main apps bundle.
I also tried to enumerate the directory for NSApplicationPath but again the only bundle available is my application default bundle. I wanted to learn this technique and make use of it to separate my resources. Any help and suggestions would be greatly appreciated. Thank you

[NSBundle bundleWithPath:[NSString stringWithFormat:#"%#/%#", [[NSBundle mainBundle] bundlePath], pathToYourBundleWithinTheDotAppDirectory];
Let me know how you get on.

Try something like this:
NSBundle* bundle=[NSBundle bundleWithIdentifier: #"bundle name"];
And make sure that you have selected these options when you have dragged the bundle to the project:

For projects with one bundle, I use:
// in this example, we load test.png from the bundle
NSString *pathToResource = [[NSBundle mainBundle] pathForResource:#"test" ofType:#"png"];
What makes this so convenient is that when you have localized files, this provides the path the the file for the current user locale. This is handy since localized files are not in the main directory, but are rather in their own subfolders (for example, English localized files are in the #"en.lproj" subfolder), and calling them by name is a hassle because you need the full path. This method gets the path for you.

Related

How to access resources during app testing

Newbie questions.
I am aware that during testing my iPhone app in the Simulator, not all resource files are available in the [NSBundle mainBundle]. I understand that the solution is to refer to [NSBundle bundleForClass:[self class]] rather than to the mainBundle.
Questions I have:
Is refering to [NSBundle bundleForClass:[self class]] valid when the app is deployed and is it good practice?
Is it good practice to define in the app delegate...
NSBundle *appBundle = [NSBundle bundleForClass:[self class]];
// or, for in final app
// NSBundle *appBundle = [NSBundle mainBundle];
... and use appBundle throughout the code? Otherwise there are too many places where I refer to [NSBundle mainBundle] that I would have to change to the bundleForClass:[self Class].
If I go with this appBundle definition, should I be doing anything else? Perhaps release the appBundle before the app delegate terminates?
Thank you!
Sleiman
mainBundle contains everything inside a bundle, the resources for your target (app). XCode tries to add all the assets into the bundle but sometimes misses or other times you may have inadvertently told XCode not to copy it into the bundle. It's important to remember to only put into the bundle what the app needs before release -- if you have test files, remove them -- because they make your app larger which eats up users storage and bandwidth.
To add/remove/inspect what is in the bundle go to the file/group inspector, the little folder icon at the top-left of XCode. Choose the project, the very top-most entry. Select a target if you have more than one. Click Build Phases and scroll down to Copy Bundle Resources. That is where you manage what gets copied into the bundle.

how to access a folder present inside project in cocoa app

I have a folder named 'Images' present in my project .The path to that folder is '/Users/username/Documents/Test/ProjectName/Images'.
How to access the images folder in cocoa app.
Thanks
If you really need to work with files and folders in bundle of your app, you could access resources folder with call:
NSURL *resourceURL [[NSBundle mainBundle] resourceURL];
Than you could work with resourceURL, reading content of folder with help of NSFileManager, as you do with regular folders and files on disk.
But that's barely needed. Usually you take resource from bundle by file URL which you obtain with call like:
NSURL *fileUrl = [[NSBundle mainBundle] URLForResource:#"user agreement" withExtension:#"rtf"];
Have a look in documentation about other variants to take paths for resources from app bundle.
You can use directly by this
NSButton *closeButton = [[NSButton alloc]initWithFrame:CGRectMake(185,215 , 15, 15)];
[closeButton setImage:[NSImage imageNamed:#"close.png"]];
the close image is now displaying in the button..
this may help you...

How to get the correct bundle instance if multiple bundles with same ID exist?

I am writing a plugin for a host application (Aperture). The plugin is deployed as a bundle and within this bundle there are frameworks needed by this plugin e.g. Sparkle.
The problem is that it is now possible that another plugin is loaded within Aperture, which also has the Sparkle framework embedded. In the Sparkle code the following preprocessor directive is defined, which is used to retrieve Sparkle's NSBundle instance:
#define SPARKLE_BUNDLE [NSBundle bundleWithIdentifier:#"org.andymatuschak.Sparkle"]
However if two plugins have their instance of Sparkle each, two bundles with the same identifier exist and of course in my case the wrong one is loaded. Anyhow I would not like to rely on chance here.
My Question
Is there a way to load the correct Sparkle bundle, the one which is embedded in my plugin?
I thought about this alternative:
#define SPARKLE_BUNDLE [NSBundle bundleForClass:[self class]]
I am not sure but I think this would break if the class is subclassed by a file located outside the bundle (like it's done in AppKit, too). Am I correct here?
if you embedded it, load it via its path not via its identifier
myPluginBundle = [NSBundle bundleForClass:self.class];
bundlePath = [myPluginBundle pathForResource:#"Sparkle"type:#"bundle"];
bundle = [NSBundle bundleAtPath:bundlePath];

How to create and use bundles in cocoa?

I have an application that I wrote that uses an external unix executable file. It needs to run this file in order to get some data needed for further processes.
Right now this executable is located in my project folder and in order to use it in my app I have hardcoded paths to it (which is bad).
I've heard that to avoid this hardcoded paths issue it's possible to use bundles.
Can anyone explain me if this is the best way to achieve what I want, and direct me how to do it if so?!
I already looked through similar questions on stackoverflow and went through this:
https://developer.apple.com/library/mac/#documentation/CoreFoundation/Conceptual/CFBundles/Introduction/Introduction.html#//apple_ref/doc/uid/10000123i
it didn't really help me so far...
You use the NSBundle object to locate your executable. You start by getting your application's bundle using [NSBundle mainBundle]. Depending on where you've placed your Unix tool, you can use NSFundle's pathForAuxiliaryExecutable: or pathForResource:ofType: to locate your executable.
For example, if your Unix tool is in your Application bundle's Resources folder, you could do the following:
NSString* toolPath = [[NSBundle mainBunble] pathForResource:#"toolname" ofType:nil]

Download localized files from server - ios programming

For localized files, for example, localizedthis.png, the path for this file can be retrieved using
[NSBundle mainBundle] pathForResource:ofType:inDirectory:forLocalization:].
The question is, if we download the files from server and store them in "Documents" folder, is there any equivalent way to do something similar to above method?
Thanks.
Bundles are essentially just directories with a specific structure. So you could put the localized files that you download into a directory like Documents/MyBundle/Contents/Resources/fr.lproj/ (for French) and instead of [NSBundle mainBundle], you'd use [NSBundle bundleWithPath:...].