Upgrade to Pro — share decks privately, control downloads, hide ads and more …

入門 ReactiveSwift / Introduction to ReactiveSwift

入門 ReactiveSwift / Introduction to ReactiveSwift

Studio Rookery

November 22, 2018
Tweet

Other Decks in Programming

Transcript

  1. ؀ڥ 3 ߲໨ όʔδϣϯ Xcode 10.0.0 Swift 4.2 Result 4.0.0

    ReactiveSwift 4.0.0 ReactiveCocoa 8.0.2 RxSwift 4.3.1 RxCocoa 4.3.1
  2. ൃදͷಈػ • RxSwiftΛ1೥൒͘Β͍࢖ͬͯͨ • ࢖͍͜ͳ͖͕ͤͯͨͦΕͱಉ࣌ʹෆຬ΋ग़͖ͯͨ • ReactiveSwiftͷ͜ͱ͕ؾʹͳ͖ͬͯͨ • ReactiveSwift࢖ͬͯΈͨΒͱͯ΋ศརͩͬͨ •

    ࠓ·Ͱແ৚݅ʹ RxSwift ΛબΜͰ͍͕ͨ΋ͬͱ৭ʑࢼ͢΂͖ͩͬ ͨ • ಉ͡Α͏ͳਓ͕͍Δ͔΋͠Εͳ͍͠೔ຊޠͷ৘ใগͳ͍ͷͰൃද͠ Α͏ 5
  3. ൃදͷಈػ • RxSwiftΛ1೥൒͘Β͍࢖ͬͯͨ • ࢖͍͜ͳ͖͕ͤͯͨͦΕͱಉ࣌ʹෆຬ΋ग़͖ͯͨ • ReactiveSwiftͷ͜ͱ͕ؾʹͳ͖ͬͯͨ • ReactiveSwift࢖ͬͯΈͨΒͱͯ΋ศརͩͬͨ •

    ࠓ·Ͱແ৚݅ʹ RxSwift ΛબΜͰ͍͕ͨ΋ͬͱ৭ʑࢼ͢΂͖ͩͬ ͨ • ಉ͡Α͏ͳਓ͕͍Δ͔΋͠Εͳ͍͠೔ຊޠͷ৘ใগͳ͍ͷͰൃද͠ Α͏ 6
  4. ൃදͷಈػ • RxSwiftΛ1೥൒͘Β͍࢖ͬͯͨ • ࢖͍͜ͳ͖͕ͤͯͨͦΕͱಉ࣌ʹෆຬ΋ग़͖ͯͨ • ReactiveSwiftͷ͜ͱ͕ؾʹͳ͖ͬͯͨ • ReactiveSwift࢖ͬͯΈͨΒͱͯ΋ศརͩͬͨ •

    ࠓ·Ͱແ৚݅ʹ RxSwift ΛબΜͰ͍͕ͨ΋ͬͱ৭ʑࢼ͢΂͖ͩͬ ͨ • ಉ͡Α͏ͳਓ͕͍Δ͔΋͠Εͳ͍͠೔ຊޠͷ৘ใগͳ͍ͷͰൃද͠ Α͏ 7
  5. ൃදͷಈػ • RxSwiftΛ1೥൒͘Β͍࢖ͬͯͨ • ࢖͍͜ͳ͖͕ͤͯͨͦΕͱಉ࣌ʹෆຬ΋ग़͖ͯͨ • ReactiveSwiftͷ͜ͱ͕ؾʹͳ͖ͬͯͨ • ReactiveSwift࢖ͬͯΈͨΒͱͯ΋ศརͩͬͨ •

    ࠓ·Ͱແ৚݅ʹ RxSwift ΛબΜͰ͍͕ͨ΋ͬͱ৭ʑࢼ͢΂͖ͩͬ ͨ • ಉ͡Α͏ͳਓ͕͍Δ͔΋͠Εͳ͍͠೔ຊޠͷ৘ใগͳ͍ͷͰൃද͠ Α͏ 8
  6. ൃදͷಈػ • RxSwiftΛ1೥൒͘Β͍࢖ͬͯͨ • ࢖͍͜ͳ͖͕ͤͯͨͦΕͱಉ࣌ʹෆຬ΋ग़͖ͯͨ • ReactiveSwiftͷ͜ͱ͕ؾʹͳ͖ͬͯͨ • ReactiveSwift࢖ͬͯΈͨΒͱͯ΋ศརͩͬͨ •

    ࠓ·Ͱແ৚݅ʹ RxSwift ΛબΜͰ͍͕ͨ΋ͬͱ৭ʑࢼ͢΂͖ͩͬ ͨ • ಉ͡Α͏ͳਓ͕͍Δ͔΋͠Εͳ͍͠೔ຊޠͷ৘ใগͳ͍ͷͰൃද͠ Α͏ 9
  7. ൃදͷಈػ • RxSwiftΛ1೥൒͘Β͍࢖ͬͯͨ • ࢖͍͜ͳ͖͕ͤͯͨͦΕͱಉ࣌ʹෆຬ΋ग़͖ͯͨ • ReactiveSwiftͷ͜ͱ͕ؾʹͳ͖ͬͯͨ • ReactiveSwift࢖ͬͯΈͨΒͱͯ΋ศརͩͬͨ •

    ࠓ·Ͱແ৚݅ʹ RxSwift ΛબΜͰ͍͕ͨ΋ͬͱ৭ʑࢼ͢΂͖ͩͬ ͨ • ಉ͡Α͏ͳਓ͕͍Δ͔΋͠Εͳ͍͠೔ຊޠͷ৘ใগͳ͍ͷͰൃද͠ Α͏ 10
  8. λʔήοτ • RxSwift ೿ • ಛʹཧ༝͸ͳ͍͚Ͳ RxSwift ͔͠࢖ͬͨ͜ͱͳ͍೿ • RxSwift

    Α͏ߟ͑ͨΒ೉͍͠ΜͪΌ͏ʁͱࢥͬͯΔ೿ • ͋Δఔ౓ Rx ͕෼͔Δਓ 12
  9. Signal/SignalProducer ͷ֓ཁ • RxSwift Ͱ͍͏ `Observable` • Hot ͳ Observable

    ͕ Signal • Cold ͳ Observable ͕ SignalProducer 25
  10. Signal<Value, Error: Swift.Error> 27 • Hot ͳ Observable • subscribe

    ͞ΕΔલ͔Βಈ͍͍ͯΔʢ͓͞Β͍ʣ • ΤϥʔΛܕύϥϝʔλͱͯ࣋ͭ͠
  11. ࢖ͬͯΈΔ 28 let (users, observer) = Signal<User, NoError>.pipe() let userNames:

    Signal<String, NoError> = users.map { $0.name } userNames.observeValues { userName in print(userName) } observer.send(value: User(id: 123, name: "fenrir")) observer.sendCompleted()
  12. ࢖ͬͯΈΔ 29 let (users, observer) = Signal<User, NoError>.pipe() let userNames:

    Signal<String, NoError> = users.map { $0.name } userNames.observeValues { userName in print(userName) } observer.send(value: User(id: 123, name: "fenrir")) observer.sendCompleted() pipe ϝιουͰ Signal ͱ ͦͷ Input Λ࡞੒͢Δ
  13. ࢖ͬͯΈΔ 30 let (users, observer) = Signal<User, NoError>.pipe() let userNames:

    Signal<String, NoError> = users.map { $0.name } userNames.observeValues { userName in print(userName) } observer.send(value: User(id: 123, name: "fenrir")) observer.sendCompleted() Signal<User, NoError> ग़ྗ୲౰
  14. ࢖ͬͯΈΔ 31 let (users, observer) = Signal<User, NoError>.pipe() let userNames:

    Signal<String, NoError> = users.map { $0.name } userNames.observeValues { userName in print(userName) } observer.send(value: User(id: 123, name: "fenrir")) observer.sendCompleted() Signal<User, NoError>.Observer ೖྗ୲౰
  15. ࢖ͬͯΈΔ 32 let (users, observer) = Signal<User, NoError>.pipe() let userNames:

    Signal<String, NoError> = users.map { $0.name } userNames.observeValues { userName in print(userName) } observer.send(value: User(id: 123, name: "fenrir")) observer.sendCompleted() map ϝιουͰ User → String ͷ Signal ΁ม׵ RxSwift ͱҧͬͯ map ͯ͠΋ Hot(=Signal) ͷ··ʂ
  16. ࢖ͬͯΈΔ 33 let (users, observer) = Signal<User, NoError>.pipe() let userNames:

    Signal<String, NoError> = users.map { $0.name } userNames.observeValues { userName in print(userName) } observer.send(value: User(id: 123, name: "fenrir")) observer.sendCompleted() `observe` ܥͷϝιουͰ Signal Λߪಡ͢Δ RxSwift Ͱ͸͓ͳ͡Έͷ disposed(by:) ૬౰ͷॲཧ͸লུͰ͖Δ
  17. ࢖ͬͯΈΔ 34 let (users, observer) = Signal<User, NoError>.pipe() let userNames:

    Signal<String, NoError> = users.map { $0.name } userNames.observeValues { userName in print(userName) } observer.send(value: User(id: 123, name: "fenrir")) observer.sendCompleted() ΠϕϯτΛૹ৴͢Δ ೖྗͱग़ྗ͕ผͷΦϒδΣΫτʹ෼͔Ε͍ͯΔͷͰ Readonly ͳ Signal Λ࡞Γ΍͍͢
  18. RxSwift ͩͱ 36 let subject = PublishSubject<User>() let userNames =

    subject.map { user -> String in print("map ͨ͠Α☺ (RxSwift)") return user.name } // 2 ճ subscribe ͢Δ let disposeBag = DisposeBag() userNames .subscribe(onNext: { name in print(name) }) .disposed(by: disposeBag) userNames .subscribe(onNext: { name in print(name) }) .disposed(by: disposeBag) // ΠϕϯτΛૹΔ subject.onNext(User(id: 123, name: "fenrir")) subject.onCompleted()
  19. RxSwift ͩͱ 37 let subject = PublishSubject<User>() let userNames =

    subject.map { user -> String in print("map ͨ͠Α☺ (RxSwift)") return user.name } // 2 ճ subscribe ͢Δ let disposeBag = DisposeBag() userNames .subscribe(onNext: { name in print(name) }) .disposed(by: disposeBag) userNames .subscribe(onNext: { name in print(name) }) .disposed(by: disposeBag) // ΠϕϯτΛૹΔ subject.onNext(User(id: 123, name: "fenrir")) subject.onCompleted() pipe ͷ୅ΘΓʹ࢖͏
 PublishSubject ͸ Hot
  20. RxSwift ͩͱ 38 let subject = PublishSubject<User>() let userNames =

    subject.map { user -> String in print("map ͨ͠Α☺ (RxSwift)") return user.name } // 2 ճ subscribe ͢Δ let disposeBag = DisposeBag() userNames .subscribe(onNext: { name in print(name) }) .disposed(by: disposeBag) userNames .subscribe(onNext: { name in print(name) }) .disposed(by: disposeBag) // ΠϕϯτΛૹΔ subject.onNext(User(id: 123, name: "fenrir")) subject.onCompleted() map ͢Δͱ cold ʹͳΔ
  21. RxSwift ͩͱ 39 let subject = PublishSubject<User>() let userNames =

    subject.map { user -> String in print("map ͨ͠Α☺ (RxSwift)") return user.name } // 2 ճ subscribe ͢Δ let disposeBag = DisposeBag() userNames .subscribe(onNext: { name in print(name) }) .disposed(by: disposeBag) userNames .subscribe(onNext: { name in print(name) }) .disposed(by: disposeBag) // ΠϕϯτΛૹΔ subject.onNext(User(id: 123, name: "fenrir")) subject.onCompleted() Կճ map ͞Ε͔ͨ෼͔ΔΑ͏ ϩάΛ࢓ࠐΜͰ͓͘
  22. RxSwift ͩͱ 40 let subject = PublishSubject<User>() let userNames =

    subject.map { user -> String in print("map ͨ͠Α☺ (RxSwift)") return user.name } // 2 ճ subscribe ͢Δ let disposeBag = DisposeBag() userNames .subscribe(onNext: { name in print(name) }) .disposed(by: disposeBag) userNames .subscribe(onNext: { name in print(name) }) .disposed(by: disposeBag) // ΠϕϯτΛૹΔ subject.onNext(User(id: 123, name: "fenrir")) subject.onCompleted() subscribe ͨ͠਺͚ͩ
 Observable ͕ੜ੒͞ΕΔ
 ɾϝϞϦͷແବݣ͍
 ɾόάͷݪҼ
 ʹͳΓಘΔ ɹɹɹ
  23. RxSwift ͩͱ 41 let subject = PublishSubject<User>() let userNames =

    subject.map { user -> String in print("map ͨ͠Α☺ (RxSwift)") return user.name } // 2 ճ subscribe ͢Δ let disposeBag = DisposeBag() userNames .subscribe(onNext: { name in print(name) }) .disposed(by: disposeBag) userNames .subscribe(onNext: { name in print(name) }) .disposed(by: disposeBag) // ΠϕϯτΛૹΔ subject.onNext(User(id: 123, name: "fenrir")) subject.onCompleted() subscribe ͨ͠਺͚ͩ
 Observable ͕ੜ੒͞ΕΔ
 ɾϝϞϦͷແବݣ͍
 ɾόάͷݪҼ
 ʹͳΓಘΔ ɹɹɹ$࣮ߦ݁Ռ ʹͬ͜Γͯ͠Δ৔߹Ͱ͸ͳ͍
  24. RxSwift ͩͱ • Hot ͔ Cold ͔ਓ͕ؒ஫ҙͯ͠औΓѻΘͳ͚Ε͹ͳΒͳ͍ 43 let userNames

    = subject // Hot .map { user -> String in // Cold print("map ͨ͠Α☺ (RxSwift)") return user.name } .share(replay: 1, scope: .forever) // Hot ཪͰԿΛ͍ͯ͠Δ͔ ཧղ͢Δͷ͸೉͍͠% Cold → Hot ͷม׵͸Մೳ͕ͩɾɾɾ
  25. ReactiveSwiftͩͱ 45 let (users, observer) = Signal<User, NoError>.pipe() let userNames:

    Signal<String, NoError> = users.map { user -> String in print("map ͨ͠Α☺ (ReactiveSwift)") return user.name } // 2 ճ subscribe ͢Δ userNames.observeValues { userName in print(userName) } userNames.observeValues { userName in print(userName) } // ΠϕϯτΛૹΔ observer.send(value: User(id: 123, name: "fenrir")) observer.sendCompleted()
  26. ReactiveSwiftͩͱ 46 let (users, observer) = Signal<User, NoError>.pipe() let userNames:

    Signal<String, NoError> = users.map { user -> String in print("map ͨ͠Α☺ (ReactiveSwift)") return user.name } // 2 ճ subscribe ͢Δ userNames.observeValues { userName in print(userName) } userNames.observeValues { userName in print(userName) } // ΠϕϯτΛૹΔ observer.send(value: User(id: 123, name: "fenrir")) observer.sendCompleted() Hot ͳ Observable Ͱ͋Δ Signal Λ༻ҙ
  27. ReactiveSwiftͩͱ 47 let (users, observer) = Signal<User, NoError>.pipe() let userNames:

    Signal<String, NoError> = users.map { user -> String in print("map ͨ͠Α☺ (ReactiveSwift)") return user.name } // 2 ճ subscribe ͢Δ userNames.observeValues { userName in print(userName) } userNames.observeValues { userName in print(userName) } // ΠϕϯτΛૹΔ observer.send(value: User(id: 123, name: "fenrir")) observer.sendCompleted() map ͯ͠΋ Signal ͳ··ʂ
  28. ReactiveSwiftͩͱ 48 let (users, observer) = Signal<User, NoError>.pipe() let userNames:

    Signal<String, NoError> = users.map { user -> String in print("map ͨ͠Α☺ (ReactiveSwift)") return user.name } // 2 ճ subscribe ͢Δ userNames.observeValues { userName in print(userName) } userNames.observeValues { userName in print(userName) } // ΠϕϯτΛૹΔ observer.send(value: User(id: 123, name: "fenrir")) observer.sendCompleted() Կճ subscribe ͯ͠΋ map ͸ 1 ౓͔࣮͠ߦ͞Εͳ͍ ☺
  29. ʢ࠶ܝʣ࢖ͬͯΈΔ 51 let (users, observer) = Signal<User, NoError>.pipe() let userNames:

    Signal<String, NoError> = users.map { $0.name } userNames.observeValues { userName in print(userName) } observer.send(value: User(id: 123, name: "fenrir")) observer.sendCompleted() Signal Λߪಡ͢Δ RxSwift Ͱ͸͓ͳ͡Έͷ disposed(by:) ૬౰ͷॲཧ͸লུͰ͖Δ
  30. ʢ࠶ܝʣ࢖ͬͯΈΔ 52 let (users, observer) = Signal<User, NoError>.pipe() let userNames:

    Signal<String, NoError> = users.map { $0.name } userNames.observeValues { userName in print(userName) } observer.send(value: User(id: 123, name: "fenrir")) observer.sendCompleted() Signal Λߪಡ͢Δ RxSwift Ͱ͸͓ͳ͡Έͷ disposed(by:) ૬౰ͷॲཧ͸লུͰ͖Δ
  31. interrupted ʹΑΔ dispose 57 var (users, observer) = Signal<User, NoError>.pipe()

    let userNames: Signal<String, NoError> = users.map { $0.name } userNames.observeValues { userName in print(userName) } observer.send(value: User(id: 123, name: "fenrir")) // ݩʑͷΠϯελϯεΛഁغ͢Δ (users, observer) = Signal<User, NoError>.pipe()
  32. interrupted ʹΑΔ dispose 58 var (users, observer) = Signal<User, NoError>.pipe()

    let userNames: Signal<String, NoError> = users.map { $0.name } userNames.observeValues { userName in print(userName) } observer.send(value: User(id: 123, name: "fenrir")) // ݩʑͷΠϯελϯεΛഁغ͢Δ (users, observer) = Signal<User, NoError>.pipe() Կ͔͠ΒͷݪҼͰ Signal ͷΠϯελϯε͕ ղ์͞ΕΔͱɾɾɾ
  33. interrupted ʹΑΔ dispose 59 var (users, observer) = Signal<User, NoError>.pipe()

    let userNames: Signal<String, NoError> = users.map { $0.name } userNames.observeValues { userName in print(userName) } observer.send(value: User(id: 123, name: "fenrir")) // ݩʑͷΠϯελϯεΛഁغ͢Δ (users, observer) = Signal<User, NoError>.pipe() Signal ͔Β `interrupted` Πϕϯτ͕఻ୡ͞ΕΔ `completed` or `failed` ͢Δલʹ ऴΘͬͪΌͬͨΑͱ͍͏ҙຯ
  34. Signal.Event 61 public enum Event { case value(Value) case failed(Error)

    case completed case interrupted } ஋ΛૹΔΠϕϯτ RxSwift Ͱ͸ next
  35. Signal.Event 62 public enum Event { case value(Value) case failed(Error)

    case completed case interrupted } ࣦഊΛૹΔΠϕϯτ RxSwift Ͱ͸ error ड͚औΔͱdispose͞ΕΔ
  36. Signal.Event 63 public enum Event { case value(Value) case failed(Error)

    case completed case interrupted } ׬ྃΛૹΔΠϕϯτ RxSwift Ͱ΋ completed ड͚औΔͱdispose͞ΕΔ
  37. Signal.Event 64 public enum Event { case value(Value) case failed(Error)

    case completed case interrupted } ߪಡ͕Ωϟϯηϧ͞Εͨ͜ͱ ΛૹΔΠϕϯτ ड͚औΔͱdispose͞ΕΔ RxSwift ʹ͸ͳ͍
  38. interrupted ʹΑΔ dispose • `interrupted` ͕ى͜Δͱࣗಈతʹ dispose ͞ΕΔ • ͜ΕʹΑΓ

    RxSwift ͷ disposed(by:) ૬౰ͷॲཧ͕
 লུͰ͖Δʂ • RxSwift ͷ “DisposeBag Λఆٛͯ͠ disposed(by:) ͠ ͯ…” ͱ͍͏͍ͭ΋ॻ͘ΞϨ͕ແ͘ͳΔ 65
  39. खಈͰ dispose ΋Ͱ͖ΔΑ 66 // ͖ͬ͞·ͰӅΕͯͨ let disposable = userNames.observeValues

    { userName in print(userName) } • खಈͰ΋ dispose Ͱ͖Δ • subscribe ܥͷϝιουͷฦΓ஋͕ RxSwift ͱಉ༷ Disposable • @discardableResult ʹͳ͍ͬͯΔͷͰීஈ͸͋·Γ ҙࣝ͠ͳ͍
  40. SignalProducer<Value, Error: Swift.Error> 68 • Cold ͳ Observable • subscribe

    ͞Ε͔ͯΒಈ͘ʢ͓͞Β͍ʣ • ΤϥʔΛܕύϥϝʔλͱͯ࣋ͭ͠
  41. ࢖ͬͯΈΔ 70 let request = URLRequest(url: URL(string: "https://example.com/")!) let session

    = URLSession.shared let data: SignalProducer<(Data, URLResponse), AnyError> = session.reactive.data(with: request) data.startWithResult { result in switch result { case .success(let data, let response): break case .failure(let error): print(error) } } `startͳΜͨΒ`ܥͷϝιουΛݺͿ͜ͱͰॳΊͯಈ࡞͢Δ ྫͰ͸ `startWithResult` ΛݺΜͰ͍Δ ·ͨɺSignal ಉ༷ dispose ͷॲཧ͸লུͰ͖Δ
  42. RxSwift ͱൺֱͭͭ͠SignalProducerΛ࡞ͬͯΈΔ 71 // subscribe ͞ΕͨΒಉظతʹ1ͭͷ value ͱ completed Λྲྀ͢

    SignalProducer<Int, APIError>(value: 1) // ReactiveSwift Observable<Int>.just(1) // RxSwift // subscribe ͞ΕͨΒಉظతʹ error Λྲྀ͢ SignalProducer<Int, APIError>(error: APIError.network) // ReactiveSwift Observable<Int>.error(APIError.network) // RxSwift // subscribe ͞ΕͨΒಉظతʹ completed Λྲྀ͢ SignalProducer<Int, APIError>.empty // ReactiveSwift Observable<Int>.empty() // RxSwift
  43. RxSwift ͱൺֱͭͭ͠SignalProducerΛ࡞ͬͯΈΔ 72 // subscribe ͞ΕͨΒಉظతʹ1ͭͷ value ͱ completed Λྲྀ͢

    SignalProducer<Int, APIError>(value: 1) // ReactiveSwift Observable<Int>.just(1) // RxSwift // subscribe ͞ΕͨΒಉظతʹ error Λྲྀ͢ SignalProducer<Int, APIError>(error: APIError.network) // ReactiveSwift Observable<Int>.error(APIError.network) // RxSwift // subscribe ͞ΕͨΒಉظతʹ completed Λྲྀ͢ SignalProducer<Int, APIError>.empty // ReactiveSwift Observable<Int>.empty() // RxSwift ඇಉظόʔδϣϯ΋࡞ͬͯΈΔ
  44. ඇಉظSignalProducer࡞ͬͯΈΔ 73 func fetchUsers(with name: String) -> SignalProducer<[User], APIError> {

    return SignalProducer<[User], APIError> { observer, lifetime in repository.fetchUsers(with: name) { result in switch result { case .success(let users): observer.send(value: users) observer.sendCompleted() case .failure(let error): observer.send(error: error) } } } }
  45. ඇಉظSignalProducer࡞ͬͯΈΔ 74 func fetchUsers(with name: String) -> SignalProducer<[User], APIError> {

    return SignalProducer<[User], APIError> { observer, lifetime in repository.fetchUsers(with: name) { result in switch result { case .success(let users): observer.send(value: users) observer.sendCompleted() case .failure(let error): observer.send(error: error) } } } } public init(_ startHandler: @escaping (Signal<Value, Error>.Observer, Lifetime) -> Void) ΠχγϟϥΠβͷҾ਺͸ΫϩʔδϟΛ1ͭ
  46. ඇಉظSignalProducer࡞ͬͯΈΔ 75 func fetchUsers(with name: String) -> SignalProducer<[User], APIError> {

    return SignalProducer<[User], APIError> { observer, lifetime in repository.fetchUsers(with: name) { result in switch result { case .success(let users): observer.send(value: users) observer.sendCompleted() case .failure(let error): observer.send(error: error) } } } } `start` ͞ΕΔͱΠχγϟϥΠβʹ౉ͨ͠ Ϋϩʔδϟ͕࣮ߦ͞ΕΔ
  47. ඇಉظSignalProducer࡞ͬͯΈΔ 76 func fetchUsers(with name: String) -> SignalProducer<[User], APIError> {

    return SignalProducer<[User], APIError> { observer, lifetime in repository.fetchUsers(with: name) { result in switch result { case .success(let users): observer.send(value: users) observer.sendCompleted() case .failure(let error): observer.send(error: error) } } } } ࣗ࡞Ϋϥεͷࣗ࡞ϝιου ඇಉظॲཧͳͷͰҾ਺ʹ completionHandler ΛऔΔ
  48. ඇಉظSignalProducer࡞ͬͯΈΔ 77 func fetchUsers(with name: String) -> SignalProducer<[User], APIError> {

    return SignalProducer<[User], APIError> { observer, lifetime in repository.fetchUsers(with: name) { result in switch result { case .success(let users): observer.send(value: users) observer.sendCompleted() case .failure(let error): observer.send(error: error) } } } } ඇಉظॲཧ͕ऴΘͬͨΒ࣮ߦ͞ΕΔ
  49. ඇಉظSignalProducer࡞ͬͯΈΔ 78 func fetchUsers(with name: String) -> SignalProducer<[User], APIError> {

    return SignalProducer<[User], APIError> { observer, lifetime in repository.fetchUsers(with: name) { result in switch result { case .success(let users): observer.send(value: users) observer.sendCompleted() case .failure(let error): observer.send(error: error) } } } } ݁ՌʹԠͯ͡ Observer ʹΠϕϯτΛૹΔ ʢ͜ͷล͸ RxSwift ͱͦΜͳʹมΘΒͳ͍Ͱ͢ʣ
  50. ReactiveSwift VS RxSwift 85 ReactiveSwift RxSwift Hot Signal Observable Cold

    Signal Producer Observable Τϥʔͷܕ ෼͔Δ ෼͔ΒΜ disposeΛলུ Ͱ͖Δ Ͱ͖ͳ͍
  51. ReactiveSwift VS RxSwift 86 ReactiveSwift RxSwift Hot Signal Observable Cold

    Signal Producer Observable Τϥʔͷܕ ෼͔Δ ෼͔ΒΜ disposeΛলུ Ͱ͖Δ Ͱ͖ͳ͍ ܕϨϕϧͰ Hot ͔ Cold ͷ۠ผ͕ͭ͘
  52. ReactiveSwift VS RxSwift 87 ReactiveSwift RxSwift Hot Signal Observable Cold

    Signal Producer Observable Τϥʔͷܕ ෼͔Δ ෼͔ΒΜ disposeΛলུ Ͱ͖Δ Ͱ͖ͳ͍ ܕϨϕϧͰΤϥʔͷछྨͷ۠ผ͕ͭ͘ `NoError`Λ࢖͑͹Τϥʔ͕ى͖ͳ͍͜ͱΛදݱͰ͖Δ
  53. ReactiveSwift VS RxSwift 88 ReactiveSwift RxSwift Hot Signal Observable Cold

    Signal Producer Observable Τϥʔͷܕ ෼͔Δ ෼͔ΒΜ disposeΛলུ Ͱ͖Δ Ͱ͖ͳ͍ RxSwiftͱൺ΂ָͯͰ͖Δ ϚχϡΞϧ dispose ΋Ͱ͖Δ
  54. Signal VS SignalProducer 90 Signal SignalProducer Hot/Cold Hot Cold ߪಡ։࢝ͷϝιου

    observeXXX startXXX ओͳੜ੒ํ๏ Signal.pipe() ৭ʑ͋Δ
  55. Signal VS SignalProducer 91 Signal SignalProducer Hot/Cold Hot Cold ߪಡ։࢝ͷϝιου

    observeXXX startXXX ओͳੜ੒ํ๏ Signal.pipe() ৭ʑ͋Δ ໋໊ͷҧ͍͕྆ऀͷҧ͍ΛࡍཱͨͤͯΔʢͱࢥ͏ʣ
  56. Signal VS SignalProducer 92 Signal SignalProducer Hot/Cold Hot Cold ߪಡ։࢝ͷϝιου

    observeXXX startXXX ओͳੜ੒ํ๏ Signal.pipe() ৭ʑ͋Δ ߪಡ։࢝͢Δ͝ͱʹ start ͞ΕΔΜͩͳ͊ ͱײ͡ΒΕΔ໋໊
  57. MutableProperty<Value> 96 • ߪಡՄೳͳ஋Λอ͍࣋ͯ͠Δ • ஋ͷมߋ͸ Signal / SignalProducer ͔ΒߪಡՄೳ

    • ಉظతʹ஋Λऔಘɾઃఆ͢Δ͜ͱ΋Ͱ͖Δ • RxSwift Ͱ͍͏ BehaviorRelay(چVariable) • ໊લ͕Θ͔Γ΍͍͢ • ReactiveSwift ʹఆٛ͞Ε͍ͯΔʢBehaviorRelay ͸ RxCocoaʹఆٛ͞Ε͍ͯΔʣ
  58. ࢖ͬͯΈΔ 97 let selectedUsers = MutableProperty<[User]>([]) // ஋ͷมߋΛ `Signal` Ͱ

    subscribe selectedUsers.signal.observeValues { selectedUsers in print(selectedUsers) } // ஋ͷมߋΛ `SignalProducer` Ͱ subscribe selectedUsers.producer.startWithValues { selectedUsers in print(selectedUsers) } // ஋ͷมߋͱऔಘ͸ value ͔ΒՄೳ selectedUsers.value = [ User(id: 123, name: "fenrir") ] selectedUsers.value.removeAll() XCTAssert(selectedUsers.value.isEmpty)
  59. ࢖ͬͯΈΔ 98 let selectedUsers = MutableProperty<[User]>([]) // ஋ͷมߋΛ `Signal` Ͱ

    subscribe selectedUsers.signal.observeValues { selectedUsers in print(selectedUsers) } // ஋ͷมߋΛ `SignalProducer` Ͱ subscribe selectedUsers.producer.startWithValues { selectedUsers in print(selectedUsers) } // ஋ͷมߋͱऔಘ͸ value ͔ΒՄೳ selectedUsers.value = [ User(id: 123, name: "fenrir") ] selectedUsers.value.removeAll() XCTAssert(selectedUsers.value.isEmpty) ॳظԽ
  60. let selectedUsers = MutableProperty<[User]>([]) // ஋ͷมߋΛ `Signal` Ͱ subscribe selectedUsers.signal.observeValues

    { selectedUsers in print(selectedUsers) } // ஋ͷมߋΛ `SignalProducer` Ͱ subscribe selectedUsers.producer.startWithValues { selectedUsers in print(selectedUsers) } // ஋ͷมߋͱऔಘ͸ value ͔ΒՄೳ selectedUsers.value = [ User(id: 123, name: "fenrir") ] selectedUsers.value.removeAll() XCTAssert(selectedUsers.value.isEmpty) ࢖ͬͯΈΔ 99 ஋ͷมߋΛߪಡͰ͖Δ ॳظ஋͸ྲྀΕͯ͜ͳ͍
  61. let selectedUsers = MutableProperty<[User]>([]) // ஋ͷมߋΛ `Signal` Ͱ subscribe selectedUsers.signal.observeValues

    { selectedUsers in print(selectedUsers) } // ஋ͷมߋΛ `SignalProducer` Ͱ subscribe selectedUsers.producer.startWithValues { selectedUsers in print(selectedUsers) } // ஋ͷมߋͱऔಘ͸ value ͔ΒՄೳ selectedUsers.value = [ User(id: 123, name: "fenrir") ] selectedUsers.value.removeAll() XCTAssert(selectedUsers.value.isEmpty) ࢖ͬͯΈΔ 100 ஋ͷมߋΛߪಡͰ͖Δ ॳظ஋͕ྲྀΕͯདྷΔ
  62. let selectedUsers = MutableProperty<[User]>([]) // ஋ͷมߋΛ `Signal` Ͱ subscribe selectedUsers.signal.observeValues

    { selectedUsers in print(selectedUsers) } // ஋ͷมߋΛ `SignalProducer` Ͱ subscribe selectedUsers.producer.startWithValues { selectedUsers in print(selectedUsers) } // ஋ͷมߋͱऔಘ͸ value ͔ΒՄೳ selectedUsers.value = [ User(id: 123, name: "fenrir") ] selectedUsers.value.removeAll() XCTAssert(selectedUsers.value.isEmpty) ࢖ͬͯΈΔ 101 ஋Λಉظతʹ
 औಘɾઃఆͰ͖Δ
  63. let mutableState = MutableProperty(State.notLoaded) mutableState.value = .loading let state =

    Property(capturing: mutableState) state.value = .notLoaded ࢖ͬͯΈΔ(1) 105 લड़ͷ௨ΓMutableProperty͸ ஋Λߋ৽Ͱ͖Δ
  64. let mutableState = MutableProperty(State.notLoaded) mutableState.value = .loading let state =

    Property(capturing: mutableState) state.value = .notLoaded ࢖ͬͯΈΔ(1) 106 mutableProperty Λ Property ʹม׵ ஋͸ৗʹݩͱͳͬͨ mutableProperty ͱಉ͡
  65. let mutableState = MutableProperty(State.notLoaded) mutableState.value = .loading let state =

    Property(capturing: mutableState) state.value = .notLoaded ࢖ͬͯΈΔ(1) 107 ಡΈऔΓઐ༻ͳͷͰίϯύΠϧΤϥʔ →Cannot assign to property: 'value' is a get-only property
  66. ࢖ͬͯΈΔ(2) 108 struct ViewModel { let state: Property<State> private let

    mutableState: MutableProperty<State> init() { self.mutableState = MutableProperty<State>(.notLoaded) self.state = Property(capturing: mutableState) } }
  67. struct ViewModel { let state: Property<State> private let mutableState: MutableProperty<State>

    init() { self.mutableState = MutableProperty<State>(.notLoaded) self.state = Property(capturing: mutableState) } } ࢖ͬͯΈΔ(2) 109 ֎෦΁ͷެ։͸ಡΈऔΓઐ༻Ͱ͋Δ Property Λ༻ҙ
  68. struct ViewModel { let state: Property<State> private let mutableState: MutableProperty<State>

    init() { self.mutableState = MutableProperty<State>(.notLoaded) self.state = Property(capturing: mutableState) } } ࢖ͬͯΈΔ(2) 110 ಺෦Ͱ͸ঢ়ଶΛมߋͰ͖ΔΑ͏ʹ MutablePropertyͰ͓࣋ͬͯ͘
  69. struct ViewModel { let state: Property<State> private let mutableState: MutableProperty<State>

    init() { self.mutableState = MutableProperty<State>(.notLoaded) self.state = Property(capturing: mutableState) } } ࢖ͬͯΈΔ(2) 111 ֎෦ʹެ։͢Δ༻ͷ Property ͸ ݩʑ͸ MutableProperty ͳͷͰ
  70. struct ViewModel { let state: Property<State> private let mutableState: MutableProperty<State>

    init() { self.mutableState = MutableProperty<State>(.notLoaded) self.state = Property(capturing: mutableState) } } ࢖ͬͯΈΔ(2) 112 ͍ͭ͜Λม͑Δͱ
  71. struct ViewModel { let state: Property<State> private let mutableState: MutableProperty<State>

    init() { self.mutableState = MutableProperty<State>(.notLoaded) self.state = Property(capturing: mutableState) } } ࢖ͬͯΈΔ(2) 113 ͍ͭ͜΋มΘΔ
  72. Property ͷ map ͕ศར 117 struct ViewModel { let userName:

    MutableProperty<String> let isEnabled: Property<Bool> init() { self.userName = MutableProperty("") self.isEnabled = userName.map { userName in userName.count >= 4 } } }
  73. Property ͷ map ͕ศར 118 struct ViewModel { let userName:

    MutableProperty<String> let isEnabled: Property<Bool> init() { self.userName = MutableProperty("") self.isEnabled = userName.map { userName in userName.count >= 4 } } } ೖྗதͷϢʔβʔ໊ ͜͜ʹόΠϯυͯ͠΄͍͠
  74. Property ͷ map ͕ศར 119 struct ViewModel { let userName:

    MutableProperty<String> let isEnabled: Property<Bool> init() { self.userName = MutableProperty("") self.isEnabled = userName.map { userName in userName.count >= 4 } } } ੾Γସ͑ϩδοΫ͸Ӆṭ͍ͨͨ͠Ί ಡΈऔΓઐ༻ʹͯ͠Δ
  75. Property ͷ map ͕ศར 120 struct ViewModel { let userName:

    MutableProperty<String> let isEnabled: Property<Bool> init() { self.userName = MutableProperty("") self.isEnabled = userName.map { userName in userName.count >= 4 } } } userNameͷ஋͕ܾ·Ε͹ isEnabledͷ஋͸Ұҙʹܾ·Δ mapϝιουΛ࢖͑͹ΑΓએݴతʹ͔͚Δ
  76. let fenrir = "fenrir" let array: Array<Int> = Array<String>(arrayLiteral: fenrir).map

    { $0.count } let property: Property<Int> = Property<String>(value: fenrir).map { $0.count } let mutable: Property<Int> = MutableProperty<String>(fenrir).map { $0.count } let relay: Observable<Int> = BehaviorRelay<String>(value: fenrir).map { $0.count }
  77. let fenrir = "fenrir" let array: Array<Int> = Array<String>(arrayLiteral: fenrir).map

    { $0.count } let property: Property<Int> = Property<String>(value: fenrir).map { $0.count } let mutable: Property<Int> = MutableProperty<String>(fenrir).map { $0.count } let relay: Observable<Int> = BehaviorRelay<String>(value: fenrir).map { $0.count } Array<Int> ← map ← Array<String>
  78. let fenrir = "fenrir" let array: Array<Int> = Array<String>(arrayLiteral: fenrir).map

    { $0.count } let property: Property<Int> = Property<String>(value: fenrir).map { $0.count } let mutable: Property<Int> = MutableProperty<String>(fenrir).map { $0.count } let relay: Observable<Int> = BehaviorRelay<String>(value: fenrir).map { $0.count } Property<Int> ← map ← Property<String>
  79. let fenrir = "fenrir" let array: Array<Int> = Array<String>(arrayLiteral: fenrir).map

    { $0.count } let property: Property<Int> = Property<String>(value: fenrir).map { $0.count } let mutable: Property<Int> = MutableProperty<String>(fenrir).map { $0.count } let relay: Observable<Int> = BehaviorRelay<String>(value: fenrir).map { $0.count } Property<Int> ← map ← MutableProperty<String>
  80. let fenrir = "fenrir" let array: Array<Int> = Array<String>(arrayLiteral: fenrir).map

    { $0.count } let property: Property<Int> = Property<String>(value: fenrir).map { $0.count } let mutable: Property<Int> = MutableProperty<String>(fenrir).map { $0.count } let relay: Observable<Int> = BehaviorRelay<String>(value: fenrir).map { $0.count } Property<Int> ← map ← MutableProperty<String> map ޙͷܕ͕ҧ͏͕ಡΈऔΓઐ༻ʹ͍͔ͨ͠Βʁ ͜ΕͰࠔΔ͜ͱ͸͋Μ·Γແ͍ Ή͠Ζ͋Γ͕͍ͨ
  81. let fenrir = "fenrir" let array: Array<Int> = Array<String>(arrayLiteral: fenrir).map

    { $0.count } let property: Property<Int> = Property<String>(value: fenrir).map { $0.count } let mutable: Property<Int> = MutableProperty<String>(fenrir).map { $0.count } let relay: Observable<Int> = BehaviorRelay<String>(value: fenrir).map { $0.count } Observable<Int> ← map ← BehaviorRelay<String>
  82. let fenrir = "fenrir" let array: Array<Int> = Array<String>(arrayLiteral: fenrir).map

    { $0.count } let property: Property<Int> = Property<String>(value: fenrir).map { $0.count } let mutable: Property<Int> = MutableProperty<String>(fenrir).map { $0.count } let relay: Observable<Int> = BehaviorRelay<String>(value: fenrir).map { $0.count } Observable<Int> ← map ← BehaviorRelay<String> map ޙͷܕ͕ObservableʹͳΔ
 ͜Ε͸Α͘෼͔Βͳ͍
  83. viewModel.userName <~ textField.reactive.continuousTextValues.map { $0 ?? "" } registerButton.reactive.isEnabled <~

    viewModel.isEnabled ࢖ͬͯΈΔ 142 ࠨลʹ͸όΠϯυ͞ΕΔଆΛஔ͘ ɾMutableProperty ɾBindingTarget ͳͲ
  84. viewModel.userName <~ textField.reactive.continuousTextValues.map { $0 ?? "" } registerButton.reactive.isEnabled <~

    viewModel.isEnabled ࢖ͬͯΈΔ 143 ӈลʹ͸஋ΛૹΔଆΛஔ͘ ɾSignal/SignalProducer ɾProperty/MutableProperty ͳͲ
  85. viewModel.userName <~ textField.reactive.continuousTextValues.map { $0 ?? "" } registerButton.reactive.isEnabled <~

    viewModel.isEnabled ࢖ͬͯΈΔ 144 ӈล͕ Property/MutableProperty ͷ৔߹͸ݱࡏͷ஋͕ଈྲྀΕͯ͘Δ ஋ͷऔΓಀ͕͠Λߟ͑ͳͯ͘ྑ͍
  86. // ࣮͸ӅΕ͍ͯͨ let disposable = registerButton.reactive.isEnabled <~ viewModel.isEnabled ࢖ͬͯΈΔ 146

    ԋࢉࢠͷ݁Ռ͸ @discardableResult ͳ Disposable Signal/SignalProducer ͱಉ༷ dispose ͷॲཧΛলུͰ͖Δ
  87. ࢖ͬͯΈΔ 157 let action = Action<String, [User], APIError> { keyword

    -> SignalProducer<[User], APIError> in repository.fetchUsers(name: keyword) } Input → String (=Ϣʔβʔ໊) Output → [User] (=ϢʔβʔҰཡ) Error → APIError (=Τϥʔ)
  88. ࢖ͬͯΈΔ 158 let action = Action<String, [User], APIError> { keyword

    -> SignalProducer<[User], APIError> in repository.fetchUsers(name: keyword) } ΠχγϟϥΠβͷҾ਺͸Ϋϩʔδϟ1ͭ ʢଞͷύλʔϯ΋͋Δʣ
  89. ࢖ͬͯΈΔ 159 let action = Action<String, [User], APIError> { keyword

    -> SignalProducer<[User], APIError> in repository.fetchUsers(name: keyword) } (Input) -> SignalProducer<Output, Error>
  90. ࢖ͬͯΈΔ 160 let action = Action<String, [User], APIError> { keyword

    -> SignalProducer<[User], APIError> in repository.fetchUsers(name: keyword) } (Input) -> SignalProducer<Output, Error>
  91. ࢖ͬͯΈΔ 161 let action = Action<String, [User], APIError> { keyword

    -> SignalProducer<[User], APIError> in repository.fetchUsers(name: keyword) } (Input) -> SignalProducer<Output, Error>
  92. ࢖ͬͯΈΔ 162 let action = Action<String, [User], APIError> { keyword

    -> SignalProducer<[User], APIError> in repository.fetchUsers(name: keyword) } (Input) -> SignalProducer<Output, Error>
  93. ࢖ͬͯΈΔ 163 let action = Action<String, [User], APIError> { keyword

    -> SignalProducer<[User], APIError> in repository.fetchUsers(name: keyword) } action.apply("fenrir").start()
  94. ࢖ͬͯΈΔ 164 let action = Action<String, [User], APIError> { keyword

    -> SignalProducer<[User], APIError> in repository.fetchUsers(name: keyword) } action.apply("fenrir").start() apply ϝιουͰ Input(=String) Λ༩͑Δ
  95. ࢖ͬͯΈΔ 165 let action = Action<String, [User], APIError> { keyword

    -> SignalProducer<[User], APIError> in repository.fetchUsers(name: keyword) } action.apply("fenrir").start() apply → start ͞ΕΔͱ ΠχγϟϥΠβʹ౉ͨ͠Ϋϩʔδϟ͕࣮ߦ͞ΕΔ ͜ͷΫϩʔδϟͷ໭Γ஋ͷ SignalProducer ͕ start͞ΕΔ
  96. ࢖ͬͯΈΔ 166 let action = Action<String, [User], APIError> { keyword

    -> SignalProducer<[User], APIError> in repository.fetchUsers(name: keyword) } action.apply("fenrir").start() action.values.observeValues { (users: [User]) in print(users) } action.errors.observeValues { (error: APIError) in print(error) } Output ͸`values`͔ΒऔಘͰ͖Δ
  97. ࢖ͬͯΈΔ 167 let action = Action<String, [User], APIError> { keyword

    -> SignalProducer<[User], APIError> in repository.fetchUsers(name: keyword) } action.apply("fenrir").start() action.values.observeValues { (users: [User]) in print(users) } action.errors.observeValues { (error: APIError) in print(error) } Error ͸`errors`͔ΒऔಘͰ͖Δ
  98. ࢖ͬͯΈΔ 168 let action = Action<String, [User], APIError> { keyword

    -> SignalProducer<[User], APIError> in repository.fetchUsers(name: keyword) } action.apply("fenrir").start() action.values.observeValues { (users: [User]) in print(users) } action.errors.observeValues { (error: APIError) in print(error) }
  99. ࢖ͬͯΈΔ 169 let action = Action<String, [User], APIError> { keyword

    -> SignalProducer<[User], APIError> in repository.fetchUsers(name: keyword) } action.apply("fenrir").start() action.values.observeValues { (users: [User]) in print(users) } action.errors.observeValues { (error: APIError) in print(error) }
  100. ࢖ͬͯΈΔ 170 let action = Action<String, [User], APIError> { keyword

    -> SignalProducer<[User], APIError> in repository.fetchUsers(name: keyword) } action.apply("fenrir").start() action.values.observeValues { (users: [User]) in print(users) } action.errors.observeValues { (error: APIError) in print(error) } activityIndicatorView.reactive.isAnimating <~ action.isExecuting
  101. ࢖ͬͯΈΔ 171 let action = Action<String, [User], APIError> { keyword

    -> SignalProducer<[User], APIError> in repository.fetchUsers(name: keyword) } action.apply("fenrir").start() action.values.observeValues { (users: [User]) in print(users) } action.errors.observeValues { (error: APIError) in print(error) } activityIndicatorView.reactive.isAnimating <~ action.isExecuting Property<Bool> action ͕࣮ߦ͍ͯ͠ΔؒͷΈ true ʹͳΔ
  102. ࢖ͬͯΈΔ 172 let action = Action<String, [User], APIError> { keyword

    -> SignalProducer<[User], APIError> in repository.fetchUsers(name: keyword) } action.apply("fenrir").start() action.values.observeValues { (users: [User]) in print(users) } action.errors.observeValues { (error: APIError) in print(error) } activityIndicatorView.reactive.isAnimating <~ action.isExecuting Πϯδέʔλͷදࣔ੾Γସ͑ͱόΠϯυ͢Δͱ͖ʹศར
  103. ࢖ͬͯΈΔ 173 let action = Action<String, [User], APIError> { keyword

    -> SignalProducer<[User], APIError> in repository.fetchUsers(name: keyword) } action.apply("fenrir").start() action.values.observeValues { (users: [User]) in print(users) } action.errors.observeValues { (error: APIError) in print(error) } activityIndicatorView.reactive.isAnimating <~ action.isExecuting action.apply("fenrir").start() action.apply("fenrir").start() action.apply("fenrir").start() action.apply("fenrir").start()
  104. ࢖ͬͯΈΔ 174 let action = Action<String, [User], APIError> { keyword

    -> SignalProducer<[User], APIError> in repository.fetchUsers(name: keyword) } action.apply("fenrir").start() action.values.observeValues { (users: [User]) in print(users) } action.errors.observeValues { (error: APIError) in print(error) } activityIndicatorView.reactive.isAnimating <~ action.isExecuting action.apply("fenrir").start() action.apply("fenrir").start() action.apply("fenrir").start() action.apply("fenrir").start() Ұ౓ʹ࣮ߦͰ͖ΔΞΫγϣϯ͸1ͭ·Ͱ ͢Ͱʹ࣮ߦதͳΒແࢹ͞ΕΔ
  105. ࢖ͬͯΈΔ 175 let action = Action<String, [User], APIError> { keyword

    -> SignalProducer<[User], APIError> in repository.fetchUsers(name: keyword) } action.apply("fenrir").start() action.values.observeValues { (users: [User]) in print(users) } action.errors.observeValues { (error: APIError) in print(error) } activityIndicatorView.reactive.isAnimating <~ action.isExecuting action.apply("fenrir").start() action.apply("fenrir").start() action.apply("fenrir").start() action.apply("fenrir").start() button.reactive.isEnabled <~ action.isEnabled
  106. ࢖ͬͯΈΔ 176 let action = Action<String, [User], APIError> { keyword

    -> SignalProducer<[User], APIError> in repository.fetchUsers(name: keyword) } action.apply("fenrir").start() action.values.observeValues { (users: [User]) in print(users) } action.errors.observeValues { (error: APIError) in print(error) } activityIndicatorView.reactive.isAnimating <~ action.isExecuting action.apply("fenrir").start() action.apply("fenrir").start() action.apply("fenrir").start() action.apply("fenrir").start() button.reactive.isEnabled <~ action.isEnabled ࣮ߦՄೳ͔Ͳ͏͔ΛόΠϯσΟϯά
  107. ࢖ͬͯΈΔ 177 // start ͢Δ͚ͩͷύλʔϯ action.apply("fenrir").start() // start ͯ͠ݸผʹ݁ՌΛϋϯυϦϯά action.apply("fenrir").startWithResult

    { result in switch result { case .success(let users): print(users) case .failure(ActionError<APIError>.disabled): print("could not execute") case .failure(ActionError<APIError>.producerFailed(let apiError)): print(apiError) } }
  108. ࢖ͬͯΈΔ 178 // start ͢Δ͚ͩͷύλʔϯ action.apply("fenrir").start() // start ͯ͠ݸผʹ݁ՌΛϋϯυϦϯά action.apply("fenrir").startWithResult

    { result in switch result { case .success(let users): print(users) case .failure(ActionError<APIError>.disabled): print("could not execute") case .failure(ActionError<APIError>.producerFailed(let apiError)): print(apiError) } } ݸผʹϋϯυϦϯά͢Δ͜ͱ΋Ͱ͖Δ ݸผʹϋϯυϦϯά͠ͳ͍ύλʔϯ ݸผʹϋϯυϦϯά͢Δύλʔϯ
  109. ࢖ͬͯΈΔ 179 // start ͢Δ͚ͩͷύλʔϯ action.apply("fenrir").start() // start ͯ͠ݸผʹ݁ՌΛϋϯυϦϯά action.apply("fenrir").startWithResult

    { result in switch result { case .success(let users): print(users) case .failure(ActionError<APIError>.disabled): print("could not execute") case .failure(ActionError<APIError>.producerFailed(let apiError)): print(apiError) } } ࣮ߦͰ͖ͨ ݁Ռ͸੒ޭͩͬͨ
  110. ࢖ͬͯΈΔ 180 // start ͢Δ͚ͩͷύλʔϯ action.apply("fenrir").start() // start ͯ͠ݸผʹ݁ՌΛϋϯυϦϯά action.apply("fenrir").startWithResult

    { result in switch result { case .success(let users): print(users) case .failure(ActionError<APIError>.disabled): print("could not execute") case .failure(ActionError<APIError>.producerFailed(let apiError)): print(apiError) } } ࣮ߦෆՄͷঢ়ଶͩͬͨ
  111. ࢖ͬͯΈΔ 181 // start ͢Δ͚ͩͷύλʔϯ action.apply("fenrir").start() // start ͯ͠ݸผʹ݁ՌΛϋϯυϦϯά action.apply("fenrir").startWithResult

    { result in switch result { case .success(let users): print(users) case .failure(ActionError<APIError>.disabled): print("could not execute") case .failure(ActionError<APIError>.producerFailed(let apiError)): print(apiError) } } ࣮ߦͰ͖ͨ ݁Ռ͸ࣦഊͩͬͨ
  112. Action͸ͲΜͳ࣌ʹ࢖͑ͦ͏͔ 182 1. Ϙλϯλοϓ 2. API ௨৴ 3. ௨৴த͸ΠϯδέʔλΛදࣔ 4.

    ੒ޭ࣌: ը໘ભҠ
 ࣦഊ࣌: ΞϥʔτΛදࣔ 5. ͨͩ͠λοϓ࿈ଧͳͲͰ௨৴͕ೋॏʹ૸Βͳ͍Α͏ʹ੍ޚ͢Δ Α͋͘Δύλʔϯʹ࢖͑ͦ͏ʂ
  113. Action ͓͞Β͍ • ࣮ߦத͔Ͳ͏͔ͷϑϥάΛ Property<Bool> ͰऔΕΔ • ࣮ߦՄೳ͔Ͳ͏͔ͷϑϥάΛ Property<Bool> ͰऔΕΔ

    • 1౓ʹ࣮ߦͰ͖Δඇಉظॲཧ͸1ͭ·Ͱ • APIݺͼग़͠ͱ૬ੑ͕͍͍ • ֶशίετߴ͍ 184