RxSwift6 の変更点まとめ

RxSwiftの6.0が公開されたので変更点をサンプル付きでまとめました。
[GitHubのリリースノート](https://github.com/ReactiveX/RxSwift/releases/tag/6.0.0)や[DEV Community](https://dev.to/freak4pc/what-s-new-in-rxswift-6-2nog)でもまとめられています。

<img width="300px" alt="New Logo" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33499/f10f5def-9169-b2a5-a1a9-9fbfc31b4da4.png">

## `dynamicMemberLookup` を使用したバインダーの自動合成

今ままでは以下のような `ExampleView` があったとき

```swift
class ExampleView: UIView { 
    var text: String
}
```

`Binder` を毎回記述することで

```swift
extension Reactive where Base: ExampleView {
    var text: Binder<String> {
       Binder(base) { base, title in 
           base.text = text
       }
    }
}
```

このように `stream` をクラスに `bind` することができました。

```swift
let exampleView = ExampleView()
Observable.of("text").bind(to: exampleView.rx.text)
```

`RxSwift 6` からは、どのクラスに対しても、Binderを自動的に合成します。そのため、上記のBinderのコードをすべて削除してコードをすっきりさせることができるようになりました。

## `Infallible`

エラーを流さない `Observable` です。

```swift
Infallible<String>.create { observer in
    observer(.next("next"))
    observer(.completed)
    // これはコンパイルエラー
    // observer(.error(NSError()))

    return Disposables.create {}
}
```

`Observable` と比べると微妙にメソッドが違います。

```swift
Observable<String>.create { observer in
    observer.on(.next("next"))
    observer.on(.error(NSError()))
    observer.on(.completed)
            
    return Disposables.create {}
}
```

また RxCocoa の `Driver` と `Signal` は常に `MainScheduler` を使用しリソースを共有するのに対して、`Infallible`、基本的に `Observable` である点が異なります。

## `drive()` と `emit()` で複数の `observer` や `relay` にバインドできるようになりました

```swift
let myButton = UIButton()
Driver.of(true).drive(myButton.rx.isEnabled, myButton.rx.isSelected)
Signal.of(true).emit(myButton.rx.isEnabled, myButton.rx.isSelected)
```

## `decode(type:decoder:)` が追加されました

Combineと同様に、Dataを出力するObservableに対して動作するデコード演算子が追加されました。

```swift
service
    .fetchJSONUsers() // Observable<Data>
    .decode(type: [Example].self, decoder: JSONDecoder()) // Observable<[Example]>
```

## `Single` が `Swift` の `Result` を使うようになりました。

subscribe の命名が変わったため警告が出るようになりました。

```swift
// RxSwift 5
// 'subscribe(onSuccess:onError:onDisposed:)' is deprecated: renamed to 'subscribe(onSuccess:onFailure:onDisposed:)'
single.subscribe(
    onSuccess: { value in
        print("Got a value: \(value)")
    },
    onError: { error in
        print("Something went wrong: \(error)")
    }
)

// RxSwift 6
single.subscribe(
    onSuccess: { value in
        print("Got a value: \(value)")
    },
    onFailure: { error in
        print("Something went wrong: \(error)")
    }
)
```

## `ReplayRelay` が追加されました

新しく `ReplaySubject` をラップした `ReplayReplay` が追加されました。
`BehaviorRelay` や `PublishRelay` と同様にエラーを流しません。

## `withUnretained` が追加されました

いままでは `weak` キーワードを使い循環参照をせずにクラスに値を渡していました。

```swift
viewModel.importantInfo
    .subscribe(onNext: { [weak self] info in 
        guard let self = self else { return }
        self.doImportantTask(with: info)
    })
    .disposed(on: disposeBag)
```

RxSwift 6 からは `withUnretained` を使うことで綺麗に記述することができます。

```swift
viewModel.importantInfo
    .withUnretained(self) // (self, info) のタプルになる
    .subscribe(onNext: { owner, info in 
        owner.doImportantTask(with: info)
    })
    .disposed(by: disposeBag)
```

## `distinctUntilChange(at:)` で Key Paths をつかるようになりました。

```swift
Observable.of(Example(text: "1"), Example(text: "2")).distinctUntilChanged(at: \.text)

struct Example {
    let text: String
}
```

## `DisposeBag` のビルダー関数でSwiftUIのようにカンマを使わずに記述することができます。

```swift
var disposeBag = DisposeBag { 
    observable1.bind(to: input1)

    observable2.drive(input2)

    observable3.subscribe(onNext: { val in 
        print("Got \(val)")
    })
}

disposeBag.insert {
    observable4.subscribe()

    observable5.bind(to: input5)
}
```

## `ignoreElements` が `Observable<Never>` を返すようになりました

※ 修正前

```swift
public func ignoreElements() {
    -> Completable {
        return self.flatMap { _ in
            return Observable<Never>.empty()
        }
        .asCompletable()
}
```

※ 修正後

```swift
public func ignoreElements() {
    -> Observable<Never> {
    self.flatMap { _ in Observable<Never>.empty() }
}
```

## `UIApplication` に `Rx` の `Extension` が追加されました

以下変数が追加されました

- `didEnterBackground`
- `willEnterForeground`
- `didFinishLaunching`
- `didBecomeActive`
- `willResignActive`
- `didReceiveMemoryWarning`
- `willTerminate`
- `significantTimeChange`
- `backgroundRefreshStatusDidChange`
- `protectedDataWillBecomeUnavailable`
- `protectedDataDidBecomeAvailable`
- `userDidTakeScreenshot`

[変更のコミット](https://github.com/ReactiveX/RxSwift/commit/c0dfb3679f131e66b2789b24d5c7e1dc4f3dd408#diff-8c8993c209fca9b3b1d9e19fbcf2a65a2248458b1ce376c153946eef3e6d7928)

# 命名変更

メソッドのリネームがありました。

| RxSwift 5 | RxSwift 6 |
|:--|:--|
| `catchError(_:)` | `catch(_:)` |
| `catchErrorJustReturn(_:)` | `catchAndReturn(_:)` |
| `elementAt(_:)` | `element(at:)` |
| `retryWhen(_:)` | `retry(when:)` |
| `takeUntil(_:)` | `take(until:)` |
| `takeUntil(behavior:_:)` | `take(until:behavior:)` |
| `takeWhile(_:)` | `take(while:)` |
| `takeWhile(behavior:_:)` | `take(while:behavior:)` |
| `take(_:)` | `take(for:)` |
| `skipWhile(_:)` | `skip(while:)` |
| `takeUntil(_:)` | `take(until:)` |
| `observeOn(_:)` | `observe(on:)` |
| `subscribeOn(_:)` | `subscribe(on:)` |

前のメソッドを使ってもエラーにはならずに以下のような警告が表示されます。

```
'catchError' is deprecated: renamed to 'catch(_:)'
```