Nib files cannot be loaded by name from main bundle - objective-c

It seems as though my nib files are included in my test target, they don't exist in the main bundle, so my app crashes on me when I am loding a nib by its name from the main bundle. I either need to find the correct bundle that includes my nib file, or I need to load a nib using a path.
Does anyone have a solution for either one? [NSBundle bundleForClass:[self class]] doesn't work. I think the nib and class files are not in the same bundle

It might help to enumerate the bundles
for (NSBundle *bundle in [NSBundle allBundles])
{
// can look for resources in bundle
locatedPath = [bundle pathForResource:resourcePath ofType:type];
// or maybe trying and load the nib from it?
UINib *nib = [UINib nibWithName:#"Blah" bundle:bundle];
// check for !nil ...
}

Related

pathForResource ofType returns nil

here is the code i am working with.
NSString* path = [[NSBundle mainBundle] pathForResource:#"file" ofType:#"plist"];
if(path == nil)
{
NSLog(#"file not found");
}
when i run this it prints file not found in the console.
my file.plist is in the supporting files folder in my cocoa project. where does mainBundle look for files at exactly. this is stumping me quite a bit. i get that it looks for the .app file, but when developing the app where doe mainBundle look?
pathForResource:ofType: only looks in the Resources folder (and localised folders). If you are placing files into dedicated folders in the bundle then you need to use pathForResource:ofType:inDirectory: and supply the directory name.
If the NSBundle you found is what you wanted through :
NSBundle *yourTargetBundle = [NSBundle mainBundle];
or
NSBundle *yourTargetBundle = [NSBundle bundleWithURL:[[NSBundle mainBundle]
URLForResource:#"YourCustomBundleName" withExtension:#"bundle"]];
And get the nil result use function: pathForResource: ofType:. Then you can log the paths of resource under yourTargetBundle:
// Given that your resource type is .png and have no sub dir
NSArray *resoursePaths = [yourTargetBundle pathsForResourcesOfType:#"png" inDirectory:nil];
NSLog(#"resoursePaths == %#",resoursePaths);
it will log all the resources path of type png. You can get the image object use:
targetImg = [[UIImage alloc] initWithContentsOfFile:#"OnePngPathYouChose"];
I think the above approach is one way to resolve the return nil situation.

Loading nib from my own bundle?

i'm trying to put NIB/XIB files in a bundle I call Configuration.bundle. When I try to load the xib from my bundle the app crashes because it can't find the xib file.
NSBundle *bundle = [NSBundle bundleWithPath:[[NSBundle mainBundle]
pathForResource:#"Configuration" ofType:#"bundle"]];
[bundle load];
NSLog(#"bundle: %#", bundle);
I get the output
bundle: NSBundle (not yet loaded)
The 'not yet loaded' part scares me a bit. Why isn't it loaded?
And finally when I try to load my nib with the view controller
ConfigViewController *configViewController = [[ConfigViewController alloc] initWithNibName:#"ConfigViewController" bundle:bundle];
I get the output
* Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Could not load NIB in bundle: 'NSBundle (not yet loaded)' with name 'ConfigViewController.xib'
I've tried both with and without .xib.
Any ideas?
The load method is used to load executable code like frameworks and these things.
Your bundle doesn't contain any executable file that you want to load, so you don't neel to call [bundle load].
If the name of the bundle ir right, then all you've written except for [bundle load] is fine.Anyways check that the path is the right ones, don't nest too much the instructions:
NSString* path=[ [NSBundle mainBundle] pathForResource: #"Configuration" ofType: #"bundle"];
If this string is the right path, then you are sure that the bundle will be loaded correctly without calling [bundle load].
First of all if a bundle is not created properly it will not get loaded. So in-order to create a proper bundle below are the steps for creating a bundle:
1. Add a new target by choosing a templete named bundle under OS X -> Framework & Libraries.
Select newly created target and change BaseSDK from OSX to Latest iOS.
Add .xibs, images or other resources which you want to use it from bundle in Build Phrases -> Copy Bundle Resources.
Add CoreFoundation framework in Build Phrases -> Link binary with Libraries.
Compile the target choosing iOS Device.
Save the newly created bundle from Products directory to some place.
Now copy that bundle into your main project. Load a bundle using below code:
NSString *path = [[NSBundle mainBundle] pathForResource:#"BundleName" ofType:#"bundle"];
NSBundle *bundle = [NSBundle bundleWithPath:path];"
You are now set with the new bundle.

How do I load a nib from a secondary process?

I have a process spawned with NSTask that needs to display a window. I started out just writing all the UI code by hand, but this has become a pain.
So, I created a new class with a xib, MyWindowController. I want to load up an instance of this controller in secondary process and have all the IBOutlets and whatnot work properly.
Here's what I've got so far:
// Get the bundle for the main application (not the subprocess).The executable lives in Contents/Helpers, so look two dirs up from its path for the main app bundle root.
NSArray *executablePathComponents = [[[NSBundle mainBundle] executableURL] pathComponents];
NSIndexSet *indexOfEveryComponentExceptLastTwo = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [executablePathComponents count] - 2)];
NSBundle *myBundle = [NSBundle bundleWithURL:[NSURL fileURLWithPathComponents:[executablePathComponents objectsAtIndexes:indexOfEveryComponentExceptLastTwo]]];
// Load the controller nib.
NSNib *windowControllerNib = [[NSNib alloc] initWithNibNamed:#"MyWindowController" bundle:myBundle];
MyWindowController *windowController = [[MyWindowController alloc] init];
NSArray *topLevelObjects = nil;
[windowControllerNib instantiateNibWithOwner:windowController topLevelObjects:topLevelObjects];
This gives me an instance of the window controller and it displays the window from the nib on screen, so this appears to work. BUT, instantiateNibWithOwner:topLevelObjects is deprecated in favor of instantiateNibWithOwner:topLevelObjects.
Using the non-deprecated method results in an exception: "-[NSNib instantiateWithOwner:topLevelObjects:]: unrecognized selector sent to instance 0x10291ab1"
At the very least I'd like to not use the deprecated method. But maybe there is a better way to approach this whole thing?

Loading and unloading of NSBundle

I'm building pluggable interface for my application. I stuck with an updates mechanism for the plugins.
Here is the code that confuses me.
- (void) unloadBundle{
[_pluginInstance release], _pluginInstance = nil;
[[self bundle] unload];
[_bundle release], _bundle = nil;
}
- (void) loadBundleWithURL:(NSURL *)bundleURL{
NSBundle *newBundle = [NSBundle bundleWithURL:bundleURL];
if (newBundle){
[self setBundle:newBundle];
[self setPluginInstance:[[[[self.bundle principalClass] alloc] init] autorelease]];
NSLog(#"New bundle: %#", self.bundle);
NSLog(#"New bundle's principal class %#", [self.bundle principalClass]);
NSLog(#"Principal class' bundle is %#", [NSBundle bundleForClass:[self.bundle principalClass]]);
NSLog(#"Plugin's class %#", [self.pluginInstance class]);
}
}
These are the methods of my wrapper around the plugin principal class. I just call unloadBundle and then loadBundleWithURL with the URL to the new version of the bundle. When executes it logs the following into console:
New bundle: NSBundle </Users/prudnikov/Work/Projects/***/Name.pluginextension> (loaded)
New bundle's principal class MyPluginClass
Principal class' bundle is NSBundle </Users/prudnikov/Library/Application Support/MyApp/PlugIns/Name.pluginextension> (not yet loaded)
Plugin's class MyPluginClass
Means that I take principal class from the new bundle, get its bundle with [NSBundle bundleForClass:] and it is old bundle.
Any ideas what I'm doing wrong?
The problem in this case was that I forgot to unload bundle in different place. I had method that was verifying that bundle is a valid plugin's bundle.
Calling principalClass loads the bundle automatically. So, calling unload is required.

Folder in resources directory!

I have a folder named "test" in my resources. I have a lot of images in there. How can I load all the images in the folder "test" in an array?
I tried with:
testArr = [[NSArray alloc] initWithArray:[[NSBundle mainBundle] pathsForResourcesOfType:#"gif" inDirectory:#"Test"]];
But it doesn't work!
Thx for your help!
greez franhu
pathsForResourcesOfType:inDirectory: gets you the filenames. Assuming you want the actual images, you might do:
NSArray *fileNames = [[NSBundle mainBundle] pathsForResourcesOfType:#"gif" inDirectory:#"Test"];
for(NSString *fileName in fileNames)
{
// load the file here and put it in another array
}
Other things to check:
Open up your application bundle and verify that the Test directory exists in it.
If you're doing this on iOS, consider using [UIImage imageNamed:] instead, which will search your bundle for the image in question automatically.