Edited at

小ネタ:UITabBarControllerに「モーダル表示するボタン」を追加する(Swift)

More than 3 years have passed since last update.

tabbar.gif

iOSアプリで、「タブバーにタブバーっぽくないアイコンを置いて、それをタップしたら画面がモーダル出てくる」というのを見かけます。それをSwiftでやってみたという小ネタです。

ポイント:

- UITabBarControllerを継承したクラスを作る

- 押したらモーダル表示する、というボタンをself.tabBarにaddSubviewしておく

- UITabBarの中のボタンは、subviewsの中で、クラスが"UITabBarButton"のものなので、ボタンの表示位置はこれを使って調整する

- UITabBarButtonは非公開クラスなので、クラス名を文字列でチェックしている。

class MyTabBarController:UITabBarController{

let button:UIButton = UIButton()

override func viewDidLoad() {
// タブバーに重ねるボタンを作成
// ここではサイズとか位置は気にしない。
let image = UIImage(named: "button")
self.button.setBackgroundImage(image, forState: .Normal)
self.button.addTarget(self, action: "openModal",
forControlEvents: UIControlEvents.TouchUpInside)

// self.view ではなくて、self.tabBar にaddSubviewする
self.tabBar.addSubview(self.button)
}

// 表示される直前にここが呼ばれるので
// ここでself.buttonの位置を調整する
override func viewDidLayoutSubviews() {
// タブバーのn番目にあるUIViewを取得してくる。
// self.tabBarButtons()は、下のextensionで追加してるメソッド
// let v = self.tabBarButtons().first // 左端タブのUIViewn
let v = self.tabBarButtons().last // 右端タブのUIView
// let v = self.tabBarButtons()[1] // 2番目のタブの位置
if let v = v {
button.frame = v.frame
}
}

// ボタンおされたらモーダル表示
func openModal(){
// モーダル表示するViewControllerは、Storyboardから拾ってくる。
let vc = self.storyboard?.instantiateViewControllerWithIdentifier("ModalViewController") as? UIViewController
if let vc = vc {
self.presentViewController(vc, animated: true, completion: nil)
}
}
}

// UITabBarControllerを拡張
extension UITabBarController{
// タブバーを構成している、内部クラスの「UITabBarButton」を探してきて、UIViewの配列として返す。
// OSのバージョンアップで使えなくなる可能性がある。
func tabBarButtons()->[UIView]{
// reduce関数は知らなければ損。
return self.tabBar.subviews.reduce([], combine: { (ret:[UIView], item:AnyObject) -> [UIView] in
if let v = item as? UIView {
// ここ、クラス判定を「文字列」でやってるから、裏技ちっく。
if v.isKindOfClass(NSClassFromString("UITabBarButton")) {
return ret + [v]
}
}
return ret
})
}
}

ちゃんと作るなら、

- 画像をちゃんと作らないと、タブバーから浮いて見えたり、背景文字が見えてしまったりする(特にサイズ違いの実機で要テスト)

- ボタンを重ねたTabBarItemは死にアイテムになるので、意味のある画面は配置しないようにする

- OSのバージョンアップ時にはテスト厚く

等など、気をつけましょう。