简体   繁体   中英

iOS - loading xib from bundle in Documents directory

I've been working on getting "custom skinnable" interfaces working for my iOS app by bundling up xibs and downloading bundles, and loading the xibs in those bundles.

I have followed the very useful instructions here to get it almost working.

loading NSBundle files on iOS

I have the bundle downloading, and unzipping and can see the xib file. I have not used any of the TestViewController code in the example, but am instead doing this when creating the view controller using the just downloaded xib:

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *filePath = [documentsDirectory stringByAppendingPathComponent:@"gg.bundle"];
    NSBundle *bundle = [NSBundle bundleWithPath:filePath];

    if ( !bundle )
    {
        NSLog(@"Error getting bundle");
    }

    MyViewController *vc = [MyViewController new];
    [vc initWithNibName:@"CustomDownloadedXib" bundle:bundle];

When I go to push this view controller onto my stack, I get this error:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Could not load NIB in bundle: 'NSBundle (not yet loaded)' with name 'CustomDownloadedXib''

The issue seems to be that my bundle is "not yet loaded." I tried forcing my bundle to load by calling:

[bundle load]

but that doesn't help.

Is my approach here incorrect? This seems like the intuitive way to do it.

Thanks in advance!

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 template named bundle under OS X -> Framework & Libraries.

  2. Select newly created target and change BaseSDK from OSX to Latest iOS.

  3. Add .xibs, images or other resources which you want to use it from bundle in Build Phrases -> Copy Bundle Resources.

  4. Add CoreFoundation framework in Build Phrases -> Link binary with Libraries.

  5. Compile the target choosing iOS Device.

  6. 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.

Following the instructions here works:

loading NSBundle files on iOS

I was just creating the bundle incorrectly!

You need to create the bundle in Xcode though because if you don't, it won't be loaded. To create, Add a New Target to your project, choose Framework & Library -> Bundle, and link to Core Foundation. Then add the xibs you want to upload to the web to the target. Build target, reveal it in Finder, compress, and upload!

After a good amount of time I figured out that this is a commonly faced problem of loading the resources via library. I was missing the step to add "CoreFramework" to link into the resource bundle and also was not copying it to the client application folder. These steps will help loading the resource bundle appropriately. #dsiddhapura's hint helped me identify these issues.

Excerpt from the Resource Programming Guide :

In UIKit, applications can load nib files only from their main bundle..

Doesn't sound like you can do what you're wanting to do. Or at least, Apple doesn't want you to do it. You can, of course, always download a .bundle with images and load them as UIImage or similar, and then save the "active" skin into a known directory which is the directory your app always looks for the images to use when displaying the interface. Changing the skin equates to replacing the image resources at that path with ones from a downloaded bundle.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM