IOS: 调用框架的视图控制器。导致“无法在捆绑包中加载 NIB”崩溃
IOS: calling framework’s View Controller. causes 'Could not load NIB in bundle‘ crash
我想将单个 View Controllers 作为框架(称为 LoginFrameWork.framework)分发,可以在任何 App 项目中导入和使用。所以在 XCode 我创建了一个 iOS Swift 框架项目,我在其中添加了一个视图控制器 用 XIB[ 实例化=29=] 显示登录视图(带有用户名、密码和按钮)。此 LoginViewController 使用 public 接口进行编码,因此它可以包含在任何应用程序中并从中使用。
框架View Controller如下:
public class LoginViewController: UIViewController {
@IBOutlet weak var emailTextField: UITextField!
@IBOutlet weak var passwordTextField: UITextField!
@IBAction func signInButton(_ sender: UIButton) {
print("username \(emailTextField.text) password \(passwordTextField.text)")
}
public override func viewDidLoad() {
super.viewDidLoad()
}
}
接下来,我创建一个 App 项目 MyApp.xcodeproj,其中包含一个视图控制器 MyAppVC 和一个按钮。单击按钮时,我想从上面创建的框架中推送 LoginViewController。
所以我创建了一个名为 MyApp.xcworkspace 的工作区。在 XCode 中添加上面创建的 LoginFrameWork.framework 和 MyApp.xcodeproj。我连接了 MyAppVC 上的单个按钮以打开 LoginViewController。
import UIKit
import LoginFrameWork
class ViewController: UIViewController {
@IBAction func launchLogin(_ sender: Any) {
//LoginSDK.start(presentingVC: self)
var loginVC = LoginViewController(nibName: "LoginViewController", bundle: nil)
// Present
self.present(loginVC, animated: true)
}
override func viewDidLoad() {
super.viewDidLoad()
}
}
然而,这会因以下错误而崩溃,这表明它找不到 LoginViewController。这可能是因为 (a) 它在库文件夹中有错误的 LoginViewController 路径,或者 (b) 框架没有安装在设备文件夹中 (c) 其他原因...
(我确实在 MyApp 项目的“常规”选项卡和“嵌入式二进制文件”部分下包含 LoginFrameWork.framework)
libc++abi: terminating with uncaught exception of type NSException
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Could not load NIB in bundle: 'NSBundle </Users/ramanmtx/Library/Developer/CoreSimulator/Devices/5C88CAFD-85B0-49E2-8641-362D6097DEA6/data/Containers/Bundle/Application/CF14B060-A662-44B7-9CC3-3C7EBD968D21/McApp.app> (loaded)' with name 'LoginViewController''
terminating with uncaught exception of type NSException
CoreSimulator 757.5 - Device: iPhone 12 Pro Max (5C88CAFD-85B0-49E2-8641-362D6097DEA6) - Runtime: iOS 14.5 (18E182) - DeviceType: iPhone 12 Pro Max
将此作为答案发布,如果没有帮助,我们很乐意删除。
我不使用 NIB/XIB 文件,所以我很难复制你正在尝试的内容,但我仍然相信我理解实际问题。它确实与此无关,但与捆绑包以及您试图从中提取东西的位置有关。
这就是我所做的。例如,假设您有三件事:
MyFramework
,其中包含
MyFile
,正在被 使用
MyProject
这在我看来就是你想要的。现在,在 你的 案例中 MyProject
导入 MyFramework
其中包含 MyFile
。但是...
在 MyProject
中,您正在尝试访问 MyFramework
包中的文件:
var loginVC = LoginViewController(nibName: "LoginViewController", bundle: nil)
以下是适合我的方法。首先,我正在访问一些非常不同的东西 - MyFramework
中的 CoreImage 内核文件,将那里的东西实例化为 CIFilters。请记住这一点,但我认为这与您想要的是一样的。
在 MyFramework
我打开捆绑文件:
func openBundleFile(_ named:String) -> String {
let myBundle = Bundle.init(identifier: "com.MyCompany.MyFramework")
let kernelPath = (myBundle?.path(forResource: "cikernels", ofType: "bundle"))! + "/" + named + ".cikernel"
do {
return try String(contentsOfFile: kernelPath)
}
catch let error as NSError {
return error.description
}
}
主要是包标识符。我不认为这对你 MyProject
有用,但它可能。
但我认为最好的路线是:
- 在
LoginViewController
中创建一个初始化器,它将
- 使用适当的包名称
访问框架内的NIB/XIB
- 并从您的视图控制器中删除 `init(nibName:bundle:)。
当然,我可能只需在您的应用程序中输入包名称即可。 :-) 但它仍然 感觉 错误 - 框架不应该要求这种硬编码!
我想将单个 View Controllers 作为框架(称为 LoginFrameWork.framework)分发,可以在任何 App 项目中导入和使用。所以在 XCode 我创建了一个 iOS Swift 框架项目,我在其中添加了一个视图控制器 用 XIB[ 实例化=29=] 显示登录视图(带有用户名、密码和按钮)。此 LoginViewController 使用 public 接口进行编码,因此它可以包含在任何应用程序中并从中使用。
框架View Controller如下:
public class LoginViewController: UIViewController {
@IBOutlet weak var emailTextField: UITextField!
@IBOutlet weak var passwordTextField: UITextField!
@IBAction func signInButton(_ sender: UIButton) {
print("username \(emailTextField.text) password \(passwordTextField.text)")
}
public override func viewDidLoad() {
super.viewDidLoad()
}
}
接下来,我创建一个 App 项目 MyApp.xcodeproj,其中包含一个视图控制器 MyAppVC 和一个按钮。单击按钮时,我想从上面创建的框架中推送 LoginViewController。
所以我创建了一个名为 MyApp.xcworkspace 的工作区。在 XCode 中添加上面创建的 LoginFrameWork.framework 和 MyApp.xcodeproj。我连接了 MyAppVC 上的单个按钮以打开 LoginViewController。
import UIKit
import LoginFrameWork
class ViewController: UIViewController {
@IBAction func launchLogin(_ sender: Any) {
//LoginSDK.start(presentingVC: self)
var loginVC = LoginViewController(nibName: "LoginViewController", bundle: nil)
// Present
self.present(loginVC, animated: true)
}
override func viewDidLoad() {
super.viewDidLoad()
}
}
然而,这会因以下错误而崩溃,这表明它找不到 LoginViewController。这可能是因为 (a) 它在库文件夹中有错误的 LoginViewController 路径,或者 (b) 框架没有安装在设备文件夹中 (c) 其他原因...
(我确实在 MyApp 项目的“常规”选项卡和“嵌入式二进制文件”部分下包含 LoginFrameWork.framework)
libc++abi: terminating with uncaught exception of type NSException
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Could not load NIB in bundle: 'NSBundle </Users/ramanmtx/Library/Developer/CoreSimulator/Devices/5C88CAFD-85B0-49E2-8641-362D6097DEA6/data/Containers/Bundle/Application/CF14B060-A662-44B7-9CC3-3C7EBD968D21/McApp.app> (loaded)' with name 'LoginViewController''
terminating with uncaught exception of type NSException
CoreSimulator 757.5 - Device: iPhone 12 Pro Max (5C88CAFD-85B0-49E2-8641-362D6097DEA6) - Runtime: iOS 14.5 (18E182) - DeviceType: iPhone 12 Pro Max
将此作为答案发布,如果没有帮助,我们很乐意删除。
我不使用 NIB/XIB 文件,所以我很难复制你正在尝试的内容,但我仍然相信我理解实际问题。它确实与此无关,但与捆绑包以及您试图从中提取东西的位置有关。
这就是我所做的。例如,假设您有三件事:
MyFramework
,其中包含MyFile
,正在被 使用
MyProject
这在我看来就是你想要的。现在,在 你的 案例中 MyProject
导入 MyFramework
其中包含 MyFile
。但是...
在 MyProject
中,您正在尝试访问 MyFramework
包中的文件:
var loginVC = LoginViewController(nibName: "LoginViewController", bundle: nil)
以下是适合我的方法。首先,我正在访问一些非常不同的东西 - MyFramework
中的 CoreImage 内核文件,将那里的东西实例化为 CIFilters。请记住这一点,但我认为这与您想要的是一样的。
在 MyFramework
我打开捆绑文件:
func openBundleFile(_ named:String) -> String {
let myBundle = Bundle.init(identifier: "com.MyCompany.MyFramework")
let kernelPath = (myBundle?.path(forResource: "cikernels", ofType: "bundle"))! + "/" + named + ".cikernel"
do {
return try String(contentsOfFile: kernelPath)
}
catch let error as NSError {
return error.description
}
}
主要是包标识符。我不认为这对你 MyProject
有用,但它可能。
但我认为最好的路线是:
- 在
LoginViewController
中创建一个初始化器,它将 - 使用适当的包名称 访问框架内的NIB/XIB
- 并从您的视图控制器中删除 `init(nibName:bundle:)。
当然,我可能只需在您的应用程序中输入包名称即可。 :-) 但它仍然 感觉 错误 - 框架不应该要求这种硬编码!