3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

RxSwift Training

Last updated at Posted at 2020-06-10

背景

  • チームでRxSwiftのオンボーディングをする機会ができた
  • オンボーディング用の資料

前提

  • Projectで使われているRxSwiftのコードが理解できることが目的で、RxSwiftの完璧な理解は目的としていない
  • Rx.playgroundを使う
  • 問題形式で進めます
  • playgroundの章ごとに問題があるので、事前に該当の章を理解してから取り組んでください🙇‍♂️

用意

Rx.playgroundをrunできるよに

  1. RxSwiftをクローン
  2. Rx.xcworkspaceを開く
  3. RxSwiftMy Mac でビルド
  4. RxExample > RxPlayground を開く

Onboarding

Introduction

(問1) Observableを変数に保持して、保持した変数をsubscribeする

_ = Observable<String>.create { observerOfString in
        print("Observable created")
        observerOfString.on(.next("😉"))
        observerOfString.on(.next("😉"))
        observerOfString.on(.completed)
        return Disposables.create()
    }
    .subscribe { event in
        print(event)
    }
Answer
let observable = Observable<String>.create { observerOfString in
    print("Observable created")
    observerOfString.on(.next("😉"))
    observerOfString.on(.next("😉"))
    observerOfString.on(.completed)
    return Disposables.create()
}

observable.subscribe { event) in
    print(event)
}

(問2) 下記のEventをObservableから流して、subscribeする

next(1)
next(2)
next(3)
completed
Answer
let observable = Observable<Int>.create { observer in
    observer.onNext(1)
    observer.onNext(2)
    observer.onNext(3)
    observer.onCompleted()
    return Disposables.create()
}

observable.subscribe { event in
    print(event)
}

(問3) 下記の実行結果はどうなるか?

_ = Observable<Int>.create { observer in
        observer.onNext(1)
        observer.onError(TestError.test)
        observer.onNext(3)
        observer.onCompleted()
        return Disposables.create()
    }
    .subscribe { event in
        print(event)
    }
Answer
next(1)
error(test)

Creating and Subscribing to Observables

(問4) 下記のEventが流れるObservableをObservable.createを使わずに生成して、subscribeする

next([1])
completed
Answer

Answer

Observable.just([1])
    .subscribe { event in
        print(event)
    }
    .disposed(by: disposeBag)

(問5) 下記のEventが流れるObservableを生成して、subscribeする

next(true)
next(false)
next(true)
error(test) // TestError.testを使用
Answer
Observable<Bool>.create { observer in
        observer.onNext(true)
        observer.onNext(false)
        observer.onNext(true)
        observer.onError(TestError.test)
        return Disposables.create()
    }
    .subscribe { event in
        print(event)
    }

Working with Subjects

(問6) 下記を実行したときの結果

let subject = BehaviorSubject(value: 1)
subject.onNext(2)
subject.onNext(3)
subject.onError(TestError.test)
subject.onNext(4)

subject.subscribe(onNext: { element in
        print(element)
    })
    .disposed(by: disposeBag)
Answer
error(test)

(問7) (問6)のコードを修正して下記の実行結果を得るには?

(BehaviorSubjectを使用、subscribe方法は同じ)

next(1)
next(2)
next(3)
error(test)
Answer
let subject = BehaviorSubject(value: 1)

subject.subscribe({ event in
        print(event)
    })
    .disposed(by: disposeBag)

subject.onNext(2)
subject.onNext(3)
subject.onError(TestError.test)

(問8) 下記の実行結果

class TestModel {
    let publishSubject = PublishSubject<Int>()

    private let behaviorSubject = BehaviorSubject<String>(value: "")
    var observable: Observable<String> {
        return behaviorSubject.asObservable()
    }

    private let disposeBag = DisposeBag()

    init() {
        publishSubject.subscribe(onNext: { [weak self] element in
                let str = element % 2 == 0 ? "A" : "B"
                self?.behaviorSubject.onNext(str)
            })
            .disposed(by: disposeBag)
    }
}

let model = TestModel()
model.observable
    .subscribe { print($0) }
    .disposed(by: disposeBag)

model.publishSubject.onNext(1)
model.publishSubject.onNext(2)
model.publishSubject.onNext(3)
Answer
next("")
next("B")
next("A")
next("B")

番外編 (RelayとTraits)

https://github.com/ReactiveX/RxSwift/blob/master/Documentation/Subjects.md#relays
https://github.com/ReactiveX/RxSwift/blob/master/Documentation/Traits.md

Combination Operators

(問9) combineLatest内の ??? の箇所を埋める

let disposeBag = DisposeBag()

let subject1 = PublishSubject<String>()
let subject2 = PublishSubject<String>()

let observable = Observable.combineLatest(
     // ???
    )

 observable.subscribe(onNext: { element1, element2 in
         print("\(element1) \(element2)")
     })
     .disposed(by: disposeBag)

subject1.onNext("🅰️")
subject2.onNext("①")
subject1.onNext("🅱️")
subject2.onNext("②")

// ① ①
// B ①
// ② ①
// ② ②
Answer
let disposeBag = DisposeBag()

let subject1 = PublishSubject<String>()
let subject2 = PublishSubject<String>()

let observable = Observable.combineLatest(
    Observable.merge(subject1, subject2),
    subject2
    )

 observable.subscribe(onNext: { element1, element2 in
         print("\(element1) \(element2)")
     })
     .disposed(by: disposeBag)

subject1.onNext("A")
subject2.onNext("①")
subject1.onNext("B")
subject2.onNext("②")

Transforming Operators

(問10) (問8)のTestModelクラスをsubscribeとBehaviorSubjectを使わずに書き換える

Answer
class TestModel {
    let publishSubject = PublishSubject<Int>()

    let observable: Observable<String>

    private let disposeBag = DisposeBag()

    init() {
        observable =  publishSubject
            .map { $0 % 2 == 0 ? "A" : "B" }
            .startWith("")
    }
}

(問11) 下記のコードを1箇所のみを修正して、期待する結果を出力させる

Result

next(false)
next(true)
next(false)

Code

func isEven(num: Int) -> Observable<Bool> {
    let isEven = num % 2 == 0
    return Observable.just(isEven)
}

let subject = PublishSubject<Int>()

subject
    .map { isEven(num: $0) }
    .subscribe { event in
        print(event)
    }
    .disposed(by: disposeBag)

subject.onNext(1)
subject.onNext(2)
subject.onNext(3)
Answer

mapflatMap

Filtering and Conditional Operators

(問12) 下記のコードの??の箇所にオペレータを入れて、期待する結果を出力させる

Result

🐱
🐷
🐱

Code

Observable.of("🐱", "🐷", "🐱", "🐵", "🐵", "🐵", "🐱", "🐱")
    // . ??
    // . ??
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)
Answer
Observable.of("🐱", "🐷", "🐱", "🐵", "🐵", "🐵", "🐱", "🐱")
    .filter { $0 != "🐵" }
    .distinctUntilChanged()
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)
}

番外編 (Hot and Cold)

概要
https://github.com/ReactiveX/RxSwift/blob/master/Documentation/HotAndColdObservables.md

Example
https://github.com/ReactiveX/RxSwift/blob/master/RxExample/RxExample/Examples/SimpleValidation/SimpleValidationViewController.swift

Next Action

RxExample を触ろう

3
2
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
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?