くま's Tech系Blog

基本的には技術で学んだことを書き留めようと思います。雑談もやるかもね!

UITabBarControllerについて

iOSの開発では必須といっていいくらいUITabBarControllerは使うと思います

今回はそんなUITabBarControllerについて記載しようと思います

UITabBarControllerはstoryboardで作成する方法とコードで実装する方法があるので両方説明しようと思います。(個人的にはコード派です)

storyboardでの作成

まずはstoryboardで作成する方法です。

プロジェクトを作成したら、ViewControllerを選択した状態で、EditorでEmbed In → TabBarControllerを選択します

f:id:kumaskun:20210211213918p:plain

TabBarControllerを選択したら下記のようにTabBarが追加されていると思います

f:id:kumaskun:20210211214045p:plain

この状態だとTabBarのメニューは1つなので、メニューを追加します

ちなみにTabBarの表示できる個数は5つまでで、Human Interface Guidelinesによると、3〜5個が理想のようです。

新しくViewControllerを追加して、最初に作成したViewControllerを選択した状態で新しく作成したViewControllerへ伸ばすといくつかの選択肢が現れます

そこからview controllersを選択します

f:id:kumaskun:20210211214753p:plain

すると、下記のようにメニューが2つになります

f:id:kumaskun:20210211214951p:plain

メニューの名前やイメージ画像などはそれぞれのメニュー画面から変更でき、TabBarの設定変更(背景色変更など)はTabBarControllerからできます

f:id:kumaskun:20210211215539p:plain

コードでの実装

UITabBarControllerの画面を作成している場合には実装で作成するクラスと紐付ける必要があります(画面自体を作成しない場合には必要ないです)

f:id:kumaskun:20210211215923p:plain

まずは、メインとなるUITabBarControllerを継承したクラスを作成します

import UIKit

class MainTabBarController: UITabBarController {
    
}

次に表示させたいメニューのクラスを作成します

表示させたいメニューのクラスはUIViewControllerを継承します

import UIKit

class FirstMenuViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

    }
}
import UIKit

class SecondMenuViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

    }
}

そして、UITabBarControllerのクラスファイルにタブとして表示させたいViewControllerを定義します

class MainTabBarController: UITabBarController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        var menuViewControllers: [UIViewController] = []
        
        let firstMenuViewController = FirstMenuViewController()
        let secondMenuViewController = SecondMenuViewController()
        
        menuViewControllers.append(firstMenuViewController)
        menuViewControllers.append(secondMenuViewController)
        
        self.setViewControllers(menuViewControllers, animated: false)
    }
}

self.setViewControllers(viewControllers, animated: false)viewControllers = menuViewControllersでも可能です

UITabBarControllerはviewControllersというプロパティを持っているためそこにメニュー群の情報(ここでのmenuViewControllers)を代入してあげればいいです

もう一歩

UITabBarControllerを継承したクラスはアプリを起動したときに最初に表示される基底となる場合が多いと思います

なので、AppdelegateのdidfinishLaunchingWithOptionsなどで下記のように定義することが多いと思います

let controller = MainTabBarController()

window?.setRootViewControllerAnimated(controller, completionHandler: {
})

storyboardを使った方法だと画面遷移がわかりやすい反面、UITabBarControllerの画面を作らないといけないのが手間な気がします

UITabBarControllerはソースコードで作成して、メニューのControllerをstoryboardで作成するのが個人的にはおすすめです!

また、個人的にはまったのがUITabBarControllerのライフサイクルです

TabBarのアイテムが2つある画面を想定して説明します

・初回起動(1つめの画面)
1つめのitem: viewDidLoad()
1つめのitem: viewWillAppear()
1つめのitem: viewDidAppear()

・TabBar : 2つ目のボタンタップ
2つ目のitem: viewDidLoad()
2つ目のitem: viewWillAppear()
1つめのitem: viewWillDisappear()
1つめのitem: viewDidDisappear()
2つ目のitem: viewDidAppear()

・TabBar : 1つ目のボタンタップ
1つめのitem: viewWillAppear()
2つ目のitem: viewWillDisappear()
2つ目のitem: viewDidDisappear()
1つめのitem: viewDidAppear()

上記からわかるように、TabBarのアイテムは初期表示されれば、再度表示してもviewDidLoad()は行われないので、注意が必要です!

参照

UITabBarControllerの使い方