NSClassFromString return nil for Bundle.main.infoDictionary



我正在以编程方式实现我的UITabBarController,尝试从Bundle.main.infoDictionary检索控制器时出错!["CFBundleExecutable"]

以下是 UITabBarController 的代码:

import UIKit
class ENTabBarController: UITabBarController {
    override func viewDidLoad() {
        super.viewDidLoad()
        addChildViewControllers()
    }
    fileprivate func addChildViewControllers() {
        addChildViewController("ENSwipeViewController", imageName: "TabBar_swipe_")
        addChildViewController("ENSocialViewController", imageName: "TabBar_social_")
        addChildViewController("ENNotificationViewController", imageName: "TabBar_notification_")
    }
    fileprivate func addChildViewController(_ childControllerName: String, imageName: String) {
        let ns = Bundle.main.infoDictionary!["CFBundleExecutable"] as! String
        let cls: AnyClass? = NSClassFromString(ns + "." + childControllerName)
        let vcClass = cls as! UIViewController.Type
        let vc = vcClass.init()

        vc.tabBarItem.image = UIImage(named: imageName)
        vc.tabBarItem.selectedImage = UIImage(named: imageName + "selected")
        let nav = UINavigationController()
        nav.addChildViewController(vc)
        addChildViewController(nav)
    }
}

错误发生在let vcClass = cls as! UIViewController.Type,并且是:

线程 1:致命错误:解开包装时意外发现 nil 可选值

以下是ENSwipeViewController的简单代码:

import UIKit
class ENSwipeViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .red
    }
}

好吧,如果您查看文档,您会发现它说:

返回值

由 aClassName 命名的类对象,如果没有该名称命名的类,则为 nil 当前已加载。如果 aClassName 为 nil,则返回 nil。

因此,由于您的ENSwipeViewController尚未加载,因此返回 nil...

您的错误是由于尝试强制解开可选值 cls 的包装引起的。类型是 AnyObject.type 因此,将以下代码行添加到您的 func 将解决您的问题。

addChildViewController

let vcClassArray: [UIViewController.Type] = [
    ENSwipeViewController.self
]
let vcClass = classArray[0] // we only have one value 
                        // if you have more you could simply make this a variable
let vc = vcClass.init()

上面的这些行替换了您在同一函数中的内容。

let vcClass = cls as! UIViewController.Type
let vc = vcClass.init()

您需要将AnyClass?转换为您要访问的类,并使用vcClass.init() init

最新更新