JavaScriptプログラマがSwift iOSアプリを2週間で作って公開してみた〜その5 UITabBarController & UINavigationController〜


JavaScriptプログラマー(JSer)がSwiftデビューして、ただ作りたいアプリを作ってみたシリーズ第5回目です。

前回はTwitter Fabricを使った認証の実装の話でした。今回は認証後に遷移するページの土台となるUIKitが提供するUITabBarController & UINavigationControllerについてです。

前回の続きで、Twitterボタンを押して認証した後に表示されるMainTabViewControllerの実装をします。

このviewの最終的完成イメージは以下のようなもので、上部のヘッダーにタイトルと設定アイコン。また、画面下部にタブを表示しています。それぞれUINavigationControllerとUITabBarControllerを用いて作っていきます。

Photo 1-15-15, 2 15 18 AM

実装方針

UINavigationControllerとUITabBarControllerはどちらもxcodeのプロジェクトを作成するとデフォルトで使用できるUIKitというパッケージに含まれています。

今回作るMainTabViewControllerはUITabBarControllerをベースとして枠を作り、それぞれタブの中身に以下の2つのViewControllerをセットします。

  • 未読記事を表示するtimelineViewController.swift
  • お気に入りを表示するfavoriteViewController.swift

上記のそれぞれのviewControllerはUINavigationControllerを使用して共通のヘッダーを持つようにします。

実装方針はMainTabViewControllerがUITabBarControllerを継承して、UINavigationViewControllerを2つ(中身がtimelineViewController、favoriteViewController)抱える形です。

UITabBarControllerを継承したMainTabViewController

import Foundation
import UIKit

class MainTabViewController: UITabBarController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
}

それぞれのTabのコンテンツとして表示するためのviewControllerを作ります。現在は空のviewControllerとして、TimelineViewControllerとFavoriteViewControllerのファイルを作成しておきます。

それぞれのviewControllerにtabBarItemというプロパティにUITabBarItemのインスタンスをセットすると、下のタブに該当のviewControllerに対するアイコンやラベルが表示されます。

MainTabViewController.swift

class MainTabViewController: UITabBarController {
    
    var timelineView: TimelineViewController!
    var favoriteView: FavoriteViewController!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        timelineView = TimelineViewController()
        favoriteView = FavoriteViewController()
        timelineView.tabBarItem = UITabBarItem(title: "記事", image: UIImage(named: "tabbar-article.png"), selectedImage: UIImage(named: "tabbar-article.png"))
        favoriteView.tabBarItem = UITabBarItem(title: "お気に入り", image: UIImage(named: "tabbar-favorite.png"), selectedImage: UIImage(named: "tabbar-favorite.png"))
    }
}

アイコンの設定

上記でUIImageでpngファイルを指定しているところがあります。その画像はxcodeのプロジェクト内にあるImages.xcassetsというフォルダにドラッグして登録されているものが読まれます。MacのFinderから画像をImages.xcassetsにドラッグしましょう。

スクリーンショット 2015-02-01 14.46.09

画像ファイルがretina対応していてx2, x3で作成している場合はファイル名の@2xをつけると、自動的にiOSアプリがディスプレイの解像度に応じて読み込む画像を変更してくれます。

e.g. tabbar-article.pngというファイルでx2のretina対応をしている場合はtabbar-article@2x.pngという名前で倍のサイズの画像をドラッグして追加

2つのUINavigationControllerをUITabBarControllerにセットする

次にヘッダー部分や遷移の機能を使用するために、UINavigationControllerのrootViewControllerとして、作成したViewControllerをセットします。

MainTabViewController.swift

class MainTabViewController: UITabBarController {
    
    var timelineView: TimelineViewController!
    var favoriteView: FavoriteViewController!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        timelineView = TimelineViewController()
        favoriteView = FavoriteViewController()
        timelineView.tabBarItem = UITabBarItem(title: "記事", image: UIImage(named: "tabbar-article.png"), selectedImage: UIImage(named: "tabbar-article.png"))
        favoriteView.tabBarItem = UITabBarItem(title: "お気に入り", image: UIImage(named: "tabbar-favorite.png"), selectedImage: UIImage(named: "tabbar-favorite.png"))
        
        var timelineNavigationController = UINavigationController(rootViewController: timelineView)
        var favoriteNavigationController = UINavigationController(rootViewController: favoriteView)
        self.setViewControllers([timelineNavigationController, favoriteNavigationController], animated: false)
    }
}

UITabBarController継承したMainTabViewControllerのselfのsetViewControllersに作成したUINavigationControllerのインスタンスをセットしています。

でもこれだけだと、ヘッダのNavigation部分に何も表示されないと思います。
起動するとこんな感じかと。

iOS Simulator Screen Shot 2015.02.01 15.19.42

共通Navigationヘッダを持つBaseTweetViewController

今回はTimeline(記事)を表示するViewControllerとFavorite(お気に入り)を表示するViewControllerで共通のヘッダを利用するので、2つのviewControllerが継承する元のviewController(BaseTweetViewController)を作成しておきます。

BaseTweetViewController.swift

import Foundation
import UIKit
import TwitterKit

class BaseTweetViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // set title
        self.navigationItem.title = "title"
    }
}

上記ではself.navigationItem.titleにdummyのタイトルをセットしていますが、タブを押したviewでそれぞれタイトルを変えるには、このBaseTweetViewControllerを継承したTimelineViewControllerとFavoriteViewControllerがそれぞれタイトルをセットします(後述)。

設定アイコンの設置

次に設定アイコンをセットして、押された時に設定パネルを表示するような処理を追加します。

BaseTweetViewController.swift

import Foundation
import UIKit
import TwitterKit

class BaseTweetViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // set title
        self.navigationItem.title = "title"

        // nav right item button
        var settingBtn:UIButton = UIButton.buttonWithType(UIButtonType.Custom) as UIButton
        settingBtn.addTarget(self, action: "onClickSetting", forControlEvents: UIControlEvents.TouchUpInside)
        settingBtn.frame = CGRectMake(0, 0, 24, 24)
        settingBtn.setImage(UIImage(named: "settings-50.png"), forState: .Normal)
        self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: settingBtn)
    }

    func onClickSetting() {
        let settingViewCtrl = SettingViewController()
        let modalView = UINavigationController(rootViewController: settingViewCtrl)
        modalView.modalTransitionStyle = UIModalTransitionStyle.CoverVertical
        self.presentViewController(modalView, animated: true, completion: nil)
    }
}

まずはUIButtonをイメージを読み込んで作成して、self.navigationItem.rightBarButtonItemにUIBarButtonItemとしてセットします。

onClickのイベントハンドラでmodalのviewを表示するための処理をします。今回は下からすっと表示されるpresentViewController(animated: true)を使用します。中身は新規に作成するSettingViewControllerを入れますが、ここの実装に関してはまた次回以降に説明します。

現在は実行して設定アイコンをタップすると、何もない画面が出現すると思います。

TimelineViewControllerのtitleの設定

左側のタブを選択しているときのNavigationにタイトルをセットします。上記で説明したBaseTweetViewControllerを継承したTimelineViewControllerで指定します。

TimelineViewController.swift

import Foundation
import UIKit

class TimelineViewController: BaseTweetViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // set navigation title
        self.navigationItem.title = "未読記事"
    }
    
}

動かすとこんな感じ。

iOS Simulator Screen Shot 2015.02.01 15.01.19

FavoriteViewControllerのtitleの設定

右側のタブを選択した時は「お気に入り」と表示します。TimelineViewControllerと同様です。

FavoriteViewController.swift

import Foundation
import UIKit

class FavoriteViewController: BaseTweetViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // set navigation title
        self.navigationItem.title = "お気に入り"
    }
}

動かしてタブの選択を切り替えると、Navigationタイトルが変わりました!
iOS Simulator Screen Shot 2015.02.01 15.01.20

ここまででUIKitが提供するUITabBarController & UINavigationControllerを使用して、とりあえず外枠として動くものができたと思います。中身のコンテンツはないですが、それは次回以降の記事で。

次回はTwitterのTimelineを表示するために必要なFabricを使ったTwitter Search APIの解説の予定です!

TwitStockerのダウンロードはこちらから。
https://itunes.apple.com/en/app/twitstocker/id958798898?l=ja&ls=1&mt=8