在执行整个init方法之前调用viewDidLoad

Den*_*eny 13 init uitabbarcontroller viewdidload ios swift

编辑:这是Xcode 6.4的完整代码示例

我有简单的iOS应用程序没有故事板.我设置rootViewControllerUIWindowAppDelegate.swift这样的:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    let tabBarController = TabBarController()

    window = UIWindow(frame: UIScreen.mainScreen().bounds)
    window?.rootViewController = tabBarController
    window?.makeKeyAndVisible()

    return true
}
Run Code Online (Sandbox Code Playgroud)

TabBarController 类的实现如下:

class TabBarController: UITabBarController {

    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)

        // Next line is called after 'viewDidLoad' method
        println("init(nibName: bundle:)")
    }

    required init(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        println("viewDidLoad")
    }

}
Run Code Online (Sandbox Code Playgroud)

当我运行应用程序时,控制台输出如下所示:

viewDidLoad
init(nibName: bundle:)
Run Code Online (Sandbox Code Playgroud)

这意味着super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)viewDidLoad方法之后调用一行一行!这仅适用于继承自的类UITabBarController.如果你使用UIViewController后代尝试这个相同的例子,一切都很好,并viewDidLoad在执行init方法后调用.

Art*_*tal 13

只保证viewDidLoad在init方法完成后才能调用.viewDidLoad在视图控制器需要加载其视图层次结构时调用.

在内部,TabBarControllerinit方法(通过调用super.init)正在做一些导致视图加载的事情.

这适用于所有视图控制器.例如:如果您创建UIViewController子类并view在init 上对其属性执行任何操作,例如添加子视图,甚至只是设置视图的backgroundColor属性 - 您将注意到相同的行为.

  • 谢谢。但是我认为这是不一致的行为,并且没有充分的记录。我将TSI发送给Apple,我很想知道他们的答案。 (2认同)

coo*_*eet 9

来自:http://www.andrewmonshizadeh.com/2015/02/23/uitabbarcontroller-is-different/

这应该不足为奇,但显然UITabBarController的行为与大多数视图控制器不同.生命周期可能总体上与它与其他视图控制器之间的"相同",但它执行的顺序不是.

也就是说,当您创建UITabBarController的子类并提供自己的自定义初始化程序时,您会注意到以一种意外的方式调用了viewDidLoad方法.也就是说,只要你调用[super init](或UITabBarController上的其他初始化程序),它就会在初始化期间调用loadView,这将导致你的viewDidLoad被调用.这可能不是您所期望的,因为大多数(所有?)其他UIViewController子类在初始化过程中不实例化它们的视图.因此,如果您提供了自定义初始化程序并希望在加载视图之前进行一些设置,然后在加载视图后添加包含的视图控制器,这将破坏您的逻辑.

解决方案是将您的设置代码实际移出标准viewDidLoad方法,并转换为在自定义初始化程序结束时调用的特殊设置方法.这让我觉得苹果应该永远不会忘记"代码味道".可能,这是因为UITabBarController需要将UITabBar添加到UIViewController的视图中,这需要视图存在.这是什么火灾loadView.