RxSwiftでLike情報の画面間共有

#グローバルな情報(今回はLikeの情報)を複数の画面間で共有する！
SNS系のアプリなどを作る際にグローバルな情報を複数の画面間で共有しないといけない場合がありますよね！例えばLikeの情報など
今回はユーザーが変更したこのLikeの情報をどうやって複数の画面で共有するかをRxSwiftを使って実践してみました。

サンプルコードは[こちら](https://github.com/Ryochan/RxOperator)！(Sample5です)

#実際何をしているのか
今回はAPI通信はせずにローカルだけで情報の共有を実装して、`cell`にも`CellModel`を保持させていません。
*Twitter APIを利用してAPI通信も行うサンプルを実装予定

やったこと
- RxSwiftを使ってタイムラインを表示(TableView)
- 詳細画面に遷移後Likeボタンを押してLike情報を更新 → タイムラインの画面でもその情報をもとにLike情報をアップデート！！！

#ステップ１: オブジェクトを`TableView`に表示

はじめに`Item`というモデルを作成します。

```swift:Item
struct Item {
    let id: Int
    let name: String
    var isLiked: Bool
}
```

そして`Driver.just`を使って`Observable`なオブジェクトを作成し、`rx_itemsWithCellIdentifier`を使って`TableView`に対してバインドを行います！

```swift:Sample5ViewController
        let items = Driver.just([
            Item(id: 1, name: "Instagram", isLiked: false),
            Item(id: 2, name: "Facebook", isLiked: true),
            Item(id: 3, name: "Twitter", isLiked: false),
            Item(id: 4, name: "Mercari", isLiked: true),
            Item(id: 5, name: "Atte", isLiked: false),
            Item(id: 6, name: "Line", isLiked: true)
        ])
        
        items
            .drive(tableView.rx_itemsWithCellIdentifier("Cell", cellType: Sample5TableViewCell.self)) { index, item, cell in
                cell.item = item
            }
            .addDisposableTo(disposeBag)
```

これでオブジェクトを`TableView`に表示できました！


#どうやって情報を複数の画面間で共有するのか？
今回Like情報を共有するにあたって`RxSwift`の`PublishSubject`を利用しています。

<img width="764" alt="Screen Shot 2016-05-06 at 3.07.09 AM.png" src="https://qiita-image-store.s3.amazonaws.com/0/80383/cb538c08-5546-5f6a-b65b-e49d17304747.png">


 ```swift:LikeSubject
class LikeSubject {
    static let ItemDidLikeNotification = PublishSubject<Item>()
}
```

`PublishSubject`は自身が`Observer`にも`Observable`にもなれる便利なものです。

これを使用してLike情報を更新した時に更新された`item`をこの`PublishSubject`に流します！
見ての通り購読したタイミングより前のオブジェクトはストリームには流れてきません。

#詳細画面のボタンのタップに応じてLike情報を更新してグローバルな川に流す。

ここでしていること
- ボタンタップのストリームを作成する。
- `Item`のLike情報を`map`内で更新する。
- ボタンタップのストリームを利用して、更新された`Item`を`PublishSubject`へ流す。
- 同じボタンタップのストリームを利用してボタンの文字を変える。

```swift:Sample5DetailViewController
        let buttonTapped = likeButton.rx_tap.asDriver()
            
        buttonTapped
            .map { [unowned self] _ -> Item in
                var item = self.item
                item.isLiked = item.isLiked ? false : true
                return item
            }
            .driveNext { updatedItem in
                
                LikeSubject.ItemDidLikeNotification
                    .onNext(updatedItem)
            }
            .addDisposableTo(disposeBag)
        
        buttonTapped
            .driveNext { [weak self] _ in
                guard let strongSelf = self else { return }
                if strongSelf.item.isLiked {
                    strongSelf.likeButton.setTitle("👎🏻ライクされていません", forState: .Normal)
                } else {
                    strongSelf.likeButton.setTitle("👍🏻ライクされています", forState: .Normal)
                }
            }
            .addDisposableTo(disposeBag)
```

ここでアップデートされた`item`をグローバルな`LikeSubject.ItemDidLikeNotification`に`onNext`しています。
この場合は`PublishSubject`を`observer`として利用しています。

```swift:Sample5DetailViewController
.driveNext { updatedItem in
                
                LikeSubject.ItemDidLikeNotification
                    .onNext(updatedItem)
            }
            .addDisposableTo(disposeBag)
```

#グローバルに流れてきた`item`を購読して、タイムラインのLike情報を更新する。

グローバルな`LikeSubject.ItemDidLikeNotification`を`cell`に`item`を渡してあげているところで購読してあげます。

ここでしていること
- `LikeSubject.ItemDidLikeNotification`に流れてくる`item`を購読する。
- `filter`を使って流れてきた`item`が`tableView`に表示するものと同じ`id`の時だけフィルターする。
- `cell`に新しく流れてきた`item`を渡してあげる。

```swift:Sample5ViewController
items
            .drive(tableView.rx_itemsWithCellIdentifier("Cell", cellType: Sample5TableViewCell.self)) { index, item, cell in
                cell.item = item
                cell.disposeBag = DisposeBag()
                
                LikeSubject.ItemDidLikeNotification
                    .filter { $0.id == item.id }
                    .subscribeNext { [weak cell] item in
                        cell?.item = item
                    }
                    .addDisposableTo(cell.disposeBag)
            }
            .addDisposableTo(disposeBag)
```

これで詳細画面でのLikeの変化を元のタイムラインでも共有できるようになりました！

#次にやりたいこと！
次はローカルだけでなくて、実際にTwitterかなにかのAPIを利用して、そしてcellに`cellModel`を持たせて共有できるサンプルを作りたいです！