ストーリーボードをつかわず、再生↔一時停止をToolbarで書くとこうなるサンプル（Playgroundサンプル付き）

## はじめに

オーディオプレーヤーの**再生↔一時停止**のようにツールバーをつくるとき、みなさんはどのように書いていますか。:thinking:

- Storyboardをつかわない
- Swift4
- NavigationControllerをつかう

こんな条件のときのサンプルが見つけられなかったので、いろいろためしながら実装した方法を紹介したいとおもいます。

実行結果は、こんな感じになります。
![audio_playground.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883/ef052268-c36b-3459-3aff-f299da42102c.gif)
この記事の最後に、Playgroundにコピペすると動作するコードを載せていますのでそちらも参考になれば:relaxed:
## 前準備

ビューの作成時に、`self.toolbarItems`をセットしておく必要があります。
`NavigationController`にツールバーを表示させる方法は、[NavigationControllerのToolbarを特定のViewControllerでのみ有効にする \- Qiita](https://qiita.com/hirocueki2/items/ec1790927545a09214f1)を参考にしてみてください。

## ボタンをトグルするコード
ボタンのオブジェクトはひとつにして`barButtonSystemItem`を`.play`と`.pause`でトグルすればいいのでは？とおもったのですが、再生ボタンと一時停止ボタンの２つのオブジェクトを用意して差し替えるのがベターな方法みたいです。

```swift
private var audioPlaying = false

// MARK: ツールバーのアイテム
private var uiPlayButtonItem : UIBarButtonItem {
  let button = UIBarButtonItem(
    barButtonSystemItem: .play,
    target: self,
    action: #selector(onButton(_:)))
  button.tag = 1
  return button
}
private var uiPauseButtonItem : UIBarButtonItem {
  let button = UIBarButtonItem(
    barButtonSystemItem: .pause,
    target: self,
    action: #selector(onButton(_:)))
  button.tag = 1 // 置換するのでtagはおなじ
  return button
}

private lazy var uiButtonItems: [UIBarButtonItem] = {
  
  let flexibleItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: nil, action: nil)
  flexibleItem.tag = 0
  return [
    flexibleItem,
    uiPauseButtonItem, // 最初は再生
    flexibleItem,
  ]
}()

@objc func onButton(_ sender: UIBarButtonItem) {
  // 再生ボタンを差し替えるので、index位置を取得する
  guard let buttonIndex = self.uiButtonItems.firstIndex(
    where: {$0.tag == 1}
  ) else {
    print( "再生ボタンのインデックスが取得できてません")
    return
  }

  if self.audioPlaying {
    self.audioPlaying = false
    self.toolbarItems?[buttonIndex] = self.uiPlayButtonItem
    return
  }

  self.audioPlaying = true
  self.toolbarItems?[buttonIndex] = self.uiPauseButtonItem
}
```

- [Swift 配列から条件にあった要素のインデックス値を取得する \- Qiita](https://qiita.com/hirocueki2/items/3491671036e9466d7fb6)


## Playgroundで試せるコード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883/73b8fa2a-11f3-f8d5-6305-78e7511f6d29.png)

以下を実行すると、冒頭のスクショのような動作になります。

```swift
import UIKit
import XCPlayground
import PlaygroundSupport

class ViewController: UIViewController {
    private var audioPlaying = false
    let label = UILabel()
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        label.textAlignment = .center
        view.addSubview(label)
    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        label.frame = view.bounds
    }
    
    // ツールバーを表示する
    override func viewWillAppear(_ animated: Bool) {
        self.toolbarItems = self.uiButtonItems
        self.updateButton()
        self.updateLabel()
        self.navigationController?.setToolbarHidden(false, animated: false)
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        self.navigationController?.setToolbarHidden(true, animated: false)
        super.viewWillDisappear(animated)
    }
    
    // MARK: ツールバーのアイテム
    private var uiPlayButtonItem : UIBarButtonItem {
      let button = UIBarButtonItem(
        barButtonSystemItem: .play,
        target: self,
        action: #selector(onButton(_:)))
      button.tag = 1
      return button
    }
    private var uiPauseButtonItem : UIBarButtonItem {
      let button = UIBarButtonItem(
        barButtonSystemItem: .pause,
        target: self,
        action: #selector(onButton(_:)))
      button.tag = 1 // 置換するのでtagはおなじ
      return button
    }

    private lazy var uiButtonItems: [UIBarButtonItem] = {
      
      let flexibleItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: nil, action: nil)
      flexibleItem.tag = 0
      return [
        flexibleItem,
        uiPauseButtonItem, // 最初は再生
        flexibleItem,
      ]
    }()
    
    func updateLabel() {
        label.text = self.audioPlaying ? "playing..." : "pause"
    }
    
    func togglePlayState() {
        self.audioPlaying = !self.audioPlaying
    }
    
    func updateButton() {
        // 再生ボタンを差し替えるので、index位置を取得する
        guard let buttonIndex = self.uiButtonItems.firstIndex(
          where: {$0.tag == 1}
        ) else {
          print( "再生ボタンのインデックスが取得できてません")
          return
        }
        if self.audioPlaying {
          self.toolbarItems?[buttonIndex] = self.uiPauseButtonItem
          return
        }
        self.toolbarItems?[buttonIndex] = self.uiPlayButtonItem
    }
    
    @objc func onButton(_ sender: UIBarButtonItem) {
        self.togglePlayState()
        self.updateButton()
        self.updateLabel()
    }
}

var ctrl = ViewController()
let navigationController = UINavigationController(rootViewController: ctrl)
navigationController.view.frame = CGRect(x: 0, y: 0, width: 320, height: 480)

PlaygroundPage.current.needsIndefiniteExecution = true
PlaygroundPage.current.liveView = navigationController.view
```