LoginSignup
13
10

More than 3 years have passed since last update.

RxSwift6 の変更点まとめ

Last updated at Posted at 2021-01-27

RxSwiftの6.0が公開されたので変更点をサンプル付きでまとめました。
GitHubのリリースノートDEV Communityでもまとめられています。

New Logo

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

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

class ExampleView: UIView { 
    var text: String
}

Binder を毎回記述することで

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

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

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

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

Infallible

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

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

    return Disposables.create {}
}

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

Observable<String>.create { observer in
    observer.on(.next("next"))
    observer.on(.error(NSError()))
    observer.on(.completed)

    return Disposables.create {}
}

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

drive()emit() で複数の observerrelay にバインドできるようになりました

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に対して動作するデコード演算子が追加されました。

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

SingleSwiftResult を使うようになりました。

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

// 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 が追加されました。
BehaviorRelayPublishRelay と同様にエラーを流しません。

withUnretained が追加されました

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

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

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

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

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

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

struct Example {
    let text: String
}

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

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)
}

ignoreElementsObservable<Never> を返すようになりました

※ 修正前

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

※ 修正後

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

UIApplicationRxExtension が追加されました

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

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

変更のコミット

命名変更

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

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(_:)'
13
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
10