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:)。

当然,我可能只需在您的应用程序中输入包名称即可。 :-) 但它仍然 感觉 错误 - 框架不应该要求这种硬编码!