SlideMenuControllerSwiftの使い方とカスタマイズ

# はじめに
こんにちは。
[SlideMenuControllerSwift](https://github.com/dekatotoro/SlideMenuControllerSwift)というiOSライブラリの使い方などについて少し悩んだので共有してみたいと思います。
至らぬ点など多々あると思いますが、コメントなど頂けたら幸いです。

※画像のリンクはGitHubから引用させていただきました
> https://github.com/dekatotoro/SlideMenuControllerSwift

![](https://github.com/dekatotoro/SlideMenuControllerSwift/blob/master/Screenshots/SlideMenuControllerSwift3.gif?raw=true)

# 導入について
実行環境は(Swift3.0.2)(Xcode8.2.1)で、CocoaPodsを利用し、サンプルを作成したいと思います。

```Podfile.rb
use_frameworks!

pod 'SlideMenuControllerSwift'
```

# サンプルや構成の確認
**今回のライブラリ本体であるSlideMenuController(ピンク色)**は左右にメニューを出す仕組みのベースとなるUIViewControllerで、メニューとなるUIViewControllerや上に乗るUIViewControllerを設定していく感じで、SlideMenuControllerはメニューを出した時に少しだけ見える**背景のようになります**。

![Phone6.png](https://qiita-image-store.s3.amazonaws.com/0/128250/b5132a6d-a229-a722-8566-c7f316df99d2.png)

# Storyboardを利用する方法
## クラスの準備
### 左右にメニューを出すベースとなるUIViewController(SlideMenuController)
SlideMenuControllerを継承したクラスを用意します。
サンプルではピンク色のものです

```SlideViewController.swift
import UIKit
import SlideMenuControllerSwift

class SlideViewController: SlideMenuController {
    
    override func awakeFromNib() {
        let mainVC = storyboard?.instantiateViewController(withIdentifier: "Main")
        let leftVC = storyboard?.instantiateViewController(withIdentifier: "Left")
        //UIViewControllerにはNavigationBarは無いためUINavigationControllerを生成しています。
        let navigationController = UINavigationController(rootViewController: mainVC!)
        //ライブラリ特有のプロパティにセット
        mainViewController = navigationController
        leftViewController = leftVC
        super.awakeFromNib()
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
}
```

### SlideMenuControllerに乗せるメインとなるUIViewController
サンプルではNavigationBarが黄緑色のものです

```MainViewController.swift
import UIKit
import SlideMenuControllerSwift

class MainViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        //NavigationBarが半透明かどうか
        navigationController?.navigationBar.isTranslucent = false
        //NavigationBarの色を変更します
        navigationController?.navigationBar.barTintColor = UIColor(red: 129/255, green: 212/255, blue: 78/255, alpha: 1)
        //NavigationBarに乗っている部品の色を変更します
        navigationController?.navigationBar.tintColor = UIColor.white
        //バーの左側にボタンを配置します(ライブラリ特有)
        addLeftBarButtonWithImage(UIImage(named: "menu")!)
    }
}
```

### SlideMenuControllerに乗せる左側のメニューとなるUIViewController
サンプルではオレンジ色のものです
UISwitchなどを乗せていますが、今回はダミーとなります。ごめんなさい

```LeftViewController.swift
import UIKit

class LeftViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }
}
```

## Storyboardの準備
- UIViewController **3つ** (ピンク色とオレンジ色と黄緑色)

<img width="493" alt="スクリーンショット 2017-04-18 0.36.07.png" src="https://qiita-image-store.s3.amazonaws.com/0/128250/73471a1f-7600-addb-f08e-8945a1136690.png">

を用意し、以下を設定しました。

||StoryboardID|CustomClass接続名|
|:-:|:-:|:-:|
|オレンジ色|Left|LeftViewController|
|ピンク色|Slide|SlideViewController|
|黄緑色|Main|MainViewController|

# 実行
今回のサンプルでは左側のメニューのみの実装でしたが、
両方または右側だけに設定することも可能です。

![memo.gif](https://qiita-image-store.s3.amazonaws.com/0/128250/d505ccac-f3c3-ba2d-20eb-4846b398762f.gif)

# SlideMenuControllerをStoryboardで管理しない方法
SlideMenuControllerをコードで作成してしまえばStoryboardやSlideMenuControllerのサブクラスを作成しなくても実装できてしまいます。
後のプロパティでscaleなどを変更し、SlideMenuControllerが画面に表示される割合が
増えた際に背景画像などを設定したい場合やstoryboardでviewの背景色を視覚的に確認したい場合などは上記の方法でも良いかもしれません。

```AppDelegate.swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let mainVC = storyboard.instantiateViewController(withIdentifier: "Main")
    let leftVC = storyboard.instantiateViewController(withIdentifier: "Left")
    let navigationController = UINavigationController(rootViewController: mainVC)
    let slideMenuController = SlideMenuController(mainViewController: navigationController, leftMenuViewController: leftVC)
    self.window?.rootViewController = slideMenuController
    self.window?.makeKeyAndVisible()
    return true
}
```

# カスタマイズについて
## NavigationBarにボタンを追加する
以下のコードで**NavigationBarButtonItem**を作成することでアクションなどを設定しなくてもメニューが開くボタンを作成することができます。
コードを記述する位置はmainViewControllerとなっているクラスで書くことができます。
mainViewControllerがUINavigationControllerの管理下でないとNavigationBarを持つことができないので注意が必要です。

```swift
//ライブラリによってExtensionされたUIViewControllerのメソッド
//左側にボタンを作成
addLeftBarButtonWithImage(_ buttonImage: UIImage)
//右側にボタンを作成
addRightBarButtonWithImage(_ buttonImage: UIImage)
```

## 設定プロパティ
**SlideMenuOptions**という構造体が持つstaticプロパティに値を入れることで様々な設定をすることができるみたいです。

|コード|説明|
|:-:|:-:|
|leftViewWidth: CGFloat = 270.0|左メニューの横幅|
|rightViewWidth CGFloat = 270.0|右メニューの横幅|
|leftBezelWidth: CGFloat? = 16.0|画面スワイプ時に感知する左からの横幅|
|rightBezelWidth: CGFloat? = 16.0|画面スワイプ時に感知する右からの横幅|
|rightPanFromBezel: Bool = true|falseにするとスワイプでメニューを開くことができなくなる※1|
|contentViewScale: CGFloat = 0.96|メニューを開いた時のmainVCの縮み率|
|opacityViewBackgroundColor: UIColor = UIColor.black|メニューを開いた時のmainVCにかかる色|
|contentViewOpacity: CGFloat = 0.5|メニューを開いた時のmainVCにかかる色のalpha値|
|contentViewDrag: Bool = false|メニューを開いた時にmainVCがメニューのwidth分ずれて表示されるかどうか|
|shadowOpacity: CGFloat = 0|影の明るさ(0)|
|shadowRadius: CGFloat = 0|影のぼかし具合(0)|
|shadowOffset: CGSize = CGSize.zero|矩形からどれだけ影がずれているか※2|
|panFromBezel: Bool = true|画面スワイプでメニューを出せるかどうか|
|animationDuration: CGFloat = 0.4|メニューを出す速度|
|hideStatusBar: Bool = true|ステータスバーを隠すかどうか|
|pointOfNoReturnWidth: CGFloat = 44.0|※3|
|simultaneousGestureRecognizers: Bool = true|複数のジェスチャーに対応するかどうか※4|
|panGesturesEnabled: Bool = true|スワイプでのメニュー開閉動作が可能かどうか|
|tapGesturesEnabled: Bool = true|タップでのメニューを閉じる動作が可能かどうか|

※1: RightにあってLeftにはない不可解なプロパティ?
※2: RightとLeft共に影をつけたい場合はどのように値を設定すれば良いのか分かりませんでした(><)
※3: ごめんなさい 値を変更しても変化を確認することができませんでした(><)
※4: mainVCなどに他のジェスチャーが含まれていた場合にも対応するかどうか?
> 関連:[gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:)](https://developer.apple.com/reference/uikit/uigesturerecognizerdelegate/1624208-gesturerecognizer)

## オプションを記述する位置
記述する位置は**SlideMenuControllerを継承したクラス**(ピンク色のVC)で、
super.viewDidLoad後でも設定ができたことを確認できましたが

> *please set them before calling the init method*

とライブラリ説明にあったので、super.init前や生成前などに呼ぶ方が良いのかもしれません。

# コードによるメニューの開閉
SlideMenuControllerのプロパティにUIViewControllerがセットされていない場合ではメニューを開くことはできません。

```swift
//　左側のメニューを開く、閉じる
openLeft()
closeLeft()
//　右側のメニューを開く、閉じる 
openRight()
closeRight()
```

# 参考にさせていただいた記事
- [SlideMenuControllerSwift GitHub](ntrollerSwift/blob/master/README.md)
- [【Swift】スライドメニューライブラリSlideMenuControllerSwiftを使ってみた Hatena Blog](http://nukenuke.hatenablog.com/entry/2015/07/16/181531)

見て頂いてありがとうございます