17
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

UITabBarControllerのライフサイクルの違いで詰まった

Last updated at Posted at 2018-06-17

TL;DR

  1. UITabBarControllerを継承したカスタムクラスを作成
    TabBarControllerとする
  2. TabBarController()する
  3. 落ちる(!?)
TabBarController
class TabBarController: UITabBarController {

    var presenter: TabBarPresentable!
    
    override func viewDidLoad() {
        super.viewDidLoad()

        presenter.viewDidLoad() // ここで落ちる presenterがnilだった
    }
}

let tabBarController = TabBarController()
tabBarController.presenter = TabBarPresenter() // presenter後入れ
window.rootViewController = tabBarController

なぜ落ちたのか?

UITabBarControllerは初期化しただけなのにviewDidLoadが呼ばれていることが判明した。
暗黙的に強制アンラップされるpresenterが初期化されていない状態でアクセスされ、ヌルポになっていたのが原因だった。

ライフサイクルの違い

以下ではUIViewControllerUITabBarControllerでそれぞれカスタムクラスを作成し表示してみる
①〜④はそれぞれのメソッドが呼ばれるタイミングです

UIViewController

class ViewController: UIViewController {
    
    init() {
        super.init(nibName: nil, bundle: nil)   // ②
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()                     // ④
    }
}

let viewController = ViewController()           // ①
window.rootViewController = viewController      // ③

viewDidLoadが呼ばれるのはViewControllerが画面に追加された後

UITabBarController

class TabBarController: UITabBarController {
    
    init() {
        super.init(nibName: nil, bundle: nil)   // ②
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()                     // ③ ← initしただけなのに呼ばれた!!
    }
}

let tabBarController = TabBarController()       // ①
window.rootViewController = tabBarController    // ④

初期化しただけでviewDidLoad()まで呼ばれてしまう!!

なぜこうなるのか?

Likely though, this is because the UITabBarController needs to add a UITabBar to the UIViewController’s view which requires that the view exist. Which is what fires loadView.

UITabBarControllerの初期化時にUIViewControllerUITabBarを追加する必要があり、そのタイミングでviewにアクセスするのでloadViewが呼ばれる。
なので、初期化しただけでもviewDidLoadが呼ばれてしまう。

まとめ

UITabBarControllerは初期化時にUITabBarを追加するためviewDidLoadが呼ばれてしまう。
これ知らなかったら気づけんな〜〜〜。

17
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?