UITabBarControllerをアイコン＆文字列のToolbarとして使う方法

UITabBarControllerは本来であればTabを押すことで表示されているViewControllerを切り替えるために使用します。

ViewController内部でメニューボタンとして使用するのであれば、多くはUIToolbarで構築します。
しかし、UIToolbarではアイコンもしくは文字列のいずれかしか表示されません。
もしアイコンと文字列の両方を表示させたいのであれば、カスタムViewを作成することも考えられます。

しかし今回はあえてUITabBarControllerを使用し、Tabを押すとメニューボタンとして機能するようにします。

# タブをメニューボタンにする
タブを選択してからViewControllerを切り替えるか判断するためのデリゲートメソッドの[tabBarController(_:shouldSelect:)](https://developer.apple.com/documentation/uikit/uitabbarcontrollerdelegate/1621166-tabbarcontroller)
を使用します。

メニューのためのダミーViewController（ここではDummyMenuViewController）タブが押下されたときは、
ViewControllerの切り替えを抑制して、メソッドを実行するようにします。


``` swift
func tabBarController(_ tabBarController: UITabBarController, func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
    switch viewController {
    case is FirstViewController:
        // trueを返すため、表示される
        break
        
    case is DummyMenuViewController:
        let vc = viewController as! DummyMenuViewController
        switch vc.menuType {
        case .bookmark:
            showBookMarkMenu()
        case .contacts:
            showContactsMenu()
        }
        // ViewControllerの表示を抑制する
        return false
        
    default:
        break
    }
    
    // ViewControllerを表示する
    return true
}
```

以下全ソース

``` swift
import UIKit

class MainTabBarController: UITabBarController {

    var tabViewControllers: [UIViewController] = []
    var mainViewController: UIViewController?
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.delegate = self
        caseSeparateViews()
        self.setViewControllers(tabViewControllers, animated: false)
    }
    
    func caseSeparateViews() {
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        
        let firstVC = storyboard.instantiateViewController(withIdentifier: "FirstViewController")
        firstVC.tabBarItem = UITabBarItem(tabBarSystemItem: UITabBarItem.SystemItem.mostRecent, tag: 1)
        firstVC.tabBarItem.badgeValue = "1"
        firstVC.tabBarItem.badgeColor = .green
        tabViewControllers.append(firstVC)
        
        // 表示はしないがタブを表示するためのダミーViewController
        let secondViewController = DummyMenuViewController()
        secondViewController.tabBarItem = UITabBarItem(tabBarSystemItem: UITabBarItem.SystemItem.bookmarks, tag: 2)
        secondViewController.menuType = .bookmark
        tabViewControllers.append(secondViewController)
        let thirdViewController = DummyMenuViewController()
        thirdViewController.menuType = .contacts
        thirdViewController.tabBarItem = UITabBarItem(tabBarSystemItem: UITabBarItem.SystemItem.contacts, tag: 3)
        tabViewControllers.append(thirdViewController)
        
        self.mainViewController = firstVC
    }
    
    func showBookMarkMenu() {
        let alert = UIAlertController(title: "Bookmark", message: "", preferredStyle: .actionSheet)
        let newAction = UIAlertAction(title: "新規", style: .default) { (action) in
            print("new")
        }
        let editAction = UIAlertAction(title: "編集", style: .default, handler: nil)
        let cancelAction = UIAlertAction(title: "キャンセル", style: .cancel, handler: nil)
        alert.addAction(newAction)
        alert.addAction(editAction)
        alert.addAction(cancelAction)
        self.mainViewController?.present(alert, animated: true, completion: nil)
    }
    
    func showContactsMenu() {
        self.mainViewController?.view.backgroundColor = .yellow
    }
}

extension MainTabBarController : UITabBarControllerDelegate {
    
    func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
        switch viewController {
        case is FirstViewController:
            // trueを返すため、表示される
            break
            
        case is DummyMenuViewController:
            let vc = viewController as! DummyMenuViewController
            switch vc.menuType {
            case .bookmark:
                showBookMarkMenu()
            case .contacts:
                showContactsMenu()
            }
            // ViewControllerの表示を抑制する
            return false
            
        default:
            break
        }
        
        // ViewControllerを表示する
        return true
    }
    
}

class DummyMenuViewController: UIViewController {
    
    enum MenuType {
        case bookmark
        case contacts
    }
    
    var menuType: MenuType = .bookmark

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        self.view.backgroundColor = .blue
    }
    
}

class FirstViewController: UIViewController {
    
    @IBOutlet weak var label: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        self.view.backgroundColor = .red
    }

}
```