从框架加载 nib 文件时出现 NSInternalInconsistencyException
NSInternalInconsistencyException when loading nib file from framework
我在 Xcode 11 上的 swift 中创建了一个名为 TestFramework 的 iOS 框架,并在目标构建设置中将其 Mach-O Type
设置为 static library
。
我在框架项目中添加了一个名为MyViewController.xib
和MyViewController.swift
的xib文件,并制作了MyViewController
classpublic
.
然后我创建一个新的 iOS 应用程序项目并将 TestFramework
作为嵌入框架添加到项目中。
我使用下面的代码来测试框架。
let bundle = Bundle(for: MyViewController.self)
print("bundle:", bundle)
let vc = MyViewController(nibName: "MyViewController", bundle: bundle)
print("ViewController:", vc)
我得到结果:
bundle: NSBundle </Users/xxx/TestApp.app> (loaded)
ViewController: <TestFramework.MyViewController: 0x7fce75403c40>
看来一切正常。
但是当我尝试显示 viewcontroller 时,它失败了。我得到了 NSInternalInconsistencyException。
self.present(vc, animated: false, completion: nil)
异常详情:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Could not load NIB in bundle: 'NSBundle </Users/xxx/TestApp.app> (loaded)' with name 'MyViewController''
任何想法。谢谢。
静态框架链接会将框架中的代码嵌入到您的应用程序中,与动态库相比,框架中的所有 类 实际上都是主包的一部分。
但是,有一种很好的方法可以使用静态框架中的资源,这可以通过创建一个资源包来实现,该资源包将与静态框架链接,然后通过专门指向该包来加载资源。
- 在你的静态框架项目中,创建一个新的 bundle
- 将您的捆绑包基础 SDK 更改为
Latest iOS
或您希望从捆绑包的 Build Settings
选项卡支持的任何平台
- 在项目检查器中,将包作为目标依赖项添加到
Build Phases
选项卡下的静态库
- 在您的测试应用程序中,链接静态框架后,将您的资源包添加到
Build Phases
选项卡中的 Copy Bundle Resources
列表。
这是用于设置的,现在您可以在代码中使用它了:
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)
您也可以在静态框架内使用此代码,但您应始终注意资源包应始终添加到使用该框架的每个应用程序的 Copy Bundle Resources
中。
在动态 libraries/frameworks 的情况下,类 将从它们的包中动态加载,因此访问资源更加直接。
我在 Xcode 11 上的 swift 中创建了一个名为 TestFramework 的 iOS 框架,并在目标构建设置中将其 Mach-O Type
设置为 static library
。
我在框架项目中添加了一个名为MyViewController.xib
和MyViewController.swift
的xib文件,并制作了MyViewController
classpublic
.
然后我创建一个新的 iOS 应用程序项目并将 TestFramework
作为嵌入框架添加到项目中。
我使用下面的代码来测试框架。
let bundle = Bundle(for: MyViewController.self)
print("bundle:", bundle)
let vc = MyViewController(nibName: "MyViewController", bundle: bundle)
print("ViewController:", vc)
我得到结果:
bundle: NSBundle </Users/xxx/TestApp.app> (loaded)
ViewController: <TestFramework.MyViewController: 0x7fce75403c40>
看来一切正常。 但是当我尝试显示 viewcontroller 时,它失败了。我得到了 NSInternalInconsistencyException。
self.present(vc, animated: false, completion: nil)
异常详情:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Could not load NIB in bundle: 'NSBundle </Users/xxx/TestApp.app> (loaded)' with name 'MyViewController''
任何想法。谢谢。
静态框架链接会将框架中的代码嵌入到您的应用程序中,与动态库相比,框架中的所有 类 实际上都是主包的一部分。
但是,有一种很好的方法可以使用静态框架中的资源,这可以通过创建一个资源包来实现,该资源包将与静态框架链接,然后通过专门指向该包来加载资源。
- 在你的静态框架项目中,创建一个新的 bundle
- 将您的捆绑包基础 SDK 更改为
Latest iOS
或您希望从捆绑包的Build Settings
选项卡支持的任何平台 - 在项目检查器中,将包作为目标依赖项添加到
Build Phases
选项卡下的静态库 - 在您的测试应用程序中,链接静态框架后,将您的资源包添加到
Build Phases
选项卡中的Copy Bundle Resources
列表。
这是用于设置的,现在您可以在代码中使用它了:
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)
您也可以在静态框架内使用此代码,但您应始终注意资源包应始终添加到使用该框架的每个应用程序的 Copy Bundle Resources
中。
在动态 libraries/frameworks 的情况下,类 将从它们的包中动态加载,因此访问资源更加直接。