0

I create an iOS framework named TestFramework in swift on Xcode 11, and set its Mach-O Type to static library in the target build settings.

I add a xib file named MyViewController.xib with MyViewController.swift into the framework project, and made the MyViewController class public.

Then I create a new iOS app project and add the TestFramework into the project as a embed framework.

I use the following code to test the framework.

let bundle = Bundle(for: MyViewController.self) print("bundle:", bundle) let vc = MyViewController(nibName: "MyViewController", bundle: bundle) print("ViewController:", vc) 

I get the result:

bundle: NSBundle </Users/xxx/TestApp.app> (loaded) ViewController: <TestFramework.MyViewController: 0x7fce75403c40> 

It seems everything's ok. But when I try to present the viewcontroller, it failed. I got the NSInternalInconsistencyException.

self.present(vc, animated: false, completion: nil) 

The exception detail:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Could not load NIB in bundle: 'NSBundle </Users/xxx/TestApp.app> (loaded)' with name 'MyViewController'' 

Any ideas. Thanks.

3
  • It seems that the Bundle(for:) initializer did not return you the bundle you expected. It looks like it returned you the main bundle. Try to compare the bundle you got from Bundle(for:) and Bundle.main. Commented Mar 6, 2020 at 10:20
  • 1
    Oh, I think that the static linking is the problem with the bundle. Commented Mar 6, 2020 at 10:24
  • @VladRusu You're right, the bundle equals Bundle.main. And after I changed the framework back to Dynamic, everything's ok. Thanks. But should I use dynamic since some tutorials told me should use static library instead. Commented Mar 6, 2020 at 11:06

1 Answer 1

1

The static framework linking will embed the code in the framework in your application and all classes from the framework will be, in fact, part of the main bundle, in contrast with dynamic libraries.

However, there is a nice way to use resources from a static framework, and that can be achieved by creating a resources bundle which will be linked with the static framework, then load the resources by specifically pointing to that bundle.

  1. In you static framework project, create a new bundle
  2. Change your bundle base SDK to Latest iOS or any platform you wish to support from the bundle's Build Settings tab
  3. From the project inspector, add the bundle as a target dependency to the static library under the Build Phases tab
  4. In your test application, after linking the static framework, add your resources bundle to the Copy Bundle Resources list from the Build Phases tab.

This is it for the setup, now you can use it in the code:

 guard let bundlePath = Bundle.main.path(forResource: "<your bundle name>" ofType: "bundle"), let bundle = Bundle(path: bundlePath) else { return } let viewController = MyViewController(nibName: "<your nib name>" bundle: bundle) 

You can use this code inside the static framework as well, but you should be always aware that the resources bundle should always be added in the Copy Bundle Resources of every app that uses that framework.

In case of dynamic libraries/frameworks, the classes will be loaded with dynamically from their bundle, so accessing the resources is more straightforward.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.