コネヒト開発者ブログ

コネヒト開発者ブログ

RxSwift 6.0の主な変更点

こんにちは!コネヒトでiOSエンジニアをやっていますyanamuraです。

RxSwiftの6.0が公開されました。

公式のWhat's new in RxSwift6はこちらです。

What's new in RxSwift 6 ? - DEV Community

細かいdiffはこちらをご覧ください。 https://github.com/ReactiveX/RxSwift/compare/5.1.1...6.0.0

------------------------------✂--------------------------------------

ここでは、RxSwift6.0にアップデートすると影響受けそうなところから見ていきたいと思います。

Breaking Changes

deprecatedだったものが消されました

変更はこちら

Deprecated

以下のものの命名が変更されました。コンパイルは通りますがwarningになります。

  • Rename catchError(:) to catch(:).
  • Rename catchErrorJustReturn(:) to catchAndReturn(:).
  • Rename elementAt(_:) to element(at:).
  • Rename retryWhen(_:) to retry(when:).
  • Rename takeUntil(:) to take(until:) and takeUntil(behavior::) to take(until:behavior:).
  • Rename takeWhile(:) to take(while:) and takeWhile(behavior::) to take(while:behavior:).
  • Rename take(_:) duration overload to take(for:) (e.g. take(for: .seconds(3))).
  • Rename skipWhile(_:) to skip(while:).
  • Rename takeUntil(_:) to take(until:).
  • Rename observeOn and subscribeOn to observe(on:) and subscribe(on:).

Single

RxSwift5まではSingleはsubscribeするとSingleEventという独自のResultみたいなものを返していましたが、これがResultに変わりました。

// RxSwift 5

public enum SingleEvent<Element> {   
    /// One and only sequence element is produced. (underlying observable sequence emits: `.next(Element)`, `.completed`)  
    case success(Element) 

    /// Sequence terminated with an error. (underlying observable sequence emits: `.error(Error)`) 
    case error(Swift.Error)   
}
// RxSwift 6

public typealias SingleEvent<Element> = Result<Element, Swift.Error>

これまでは .error, onError としていたところを .failure, onFailure に変更しないとwarningになります。

変更のコミットはこちら

New

全てのReactiveCompatibleなオブジェクトのプロパティでBinderの実装が不要に

これまではclassのプロパティを

class MyView: UIView { 
    var title: String
}

このようにbind(to:)できるようにするには

viewModel.title.bind(to: myView.rx.title)

下記のような記述を書く必要がありました。

// RxSwift 5

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

RxSwift6ではReactiveCompatibleなオブジェクト(.rxの使えるオブジェクト)ではこの記述は不要になります。

変更のコミットはこちら

withUnretained

ObservableTypeに withUnretained が追加されました。

これまでは[weak self]をいちいち書く必要がありましたが

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

withUnretainedを使うことでoptional bindingが不要になります。

viewModel.importantInfo
  .withUnretained(self)
  .subscribe(onNext: { owner, info in 
    owner.doImportantTask(with: info)
  })
  .disposed(by: disposeBag)

変更のコミットはこちら

decode(type:decoder:)

Observabledecode(type:decoder:) が追加されました。

decodeがメソッドチェーンですっきりとかけるようになりました。

func test() {
    let rawJSON = """
        [
          {"id": 1, "name": "Foo", "country": "Foo"},
          {"id": 2, "name": "Bar"}
        ]
        """.data(using: .utf8)!

    Observable
              .just(rawJSON)
              .decode(type: [FakeObject].self, decoder: JSONDecoder())
}

private struct FakeObject: Equatable, Decodable {
  let id: Int
  let name: String
  let country: String?
}

変更のコミットはこちら

driveとemitで複数のobserverにbinding

driveとemitでは一つにしかbindingできませんでしたが、複数できるようになりました。

viewModel.string.drive(input1, input2, input3)
viewModel.number.emit(input4, input5)

変更はこちらこちら

Infallible

RxSwiftにInfallibleが追加されました。

errorを流さないObservableです。似たようなものにRxCocoaのDriverやSignalがありますが、これらと違うのはメインスレッドは保証されないのとresourceをshareしたりreplayしない点です。

実装はこちら

ReplayRelay

ReplayRelayが追加されました。

PublishRelay, BehaviorRelayと同様にReplaySubjectのwrapperでerrorやcompleteを流しません。

変更のコミットはこちら

distinctUntilChanged(at:)

distinctUntilChanged(at:) が追加されdistinctUntilChangedにkeyPathを使うことができるようになりました。

        struct TestObject: Equatable {
            let value: Int
            let other = ""
        }

        Observable<TestObject>
            .create { observer in
                observer.onNext(TestObject(value: 1))
                observer.onNext(TestObject(value: 1))
                observer.onNext(TestObject(value: 2))
                return Disposables.create()
            }
            .distinctUntilChanged(at: \.value)
            .subscribe(onNext: {
                print($0.value)
            })

変更のコミットはこちら

UIApplication.rx

UIApplicationのLife cycle Eventなどが追加されました。

追加されたものはこちらです。

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

変更のコミットはこちら