$30 off During Our Annual Pro Sale. View Details »

入門 ReactiveSwift / Introduction to ReactiveSwift

入門 ReactiveSwift / Introduction to ReactiveSwift

Studio Rookery

November 22, 2018
Tweet

Other Decks in Programming

Transcript

  1. ೖ໳ ReactiveSwift  XFE

  2. ΋͘͡ •ൃදͷಈػ •λʔήοτͱ࠷ऴ໨ඪ •ReactiveSwift ͷ֓ཁ •Signal / SignalProducer •Property /

    MutableProperty •όΠϯσΟϯάԋࢉࢠ •Action •·ͱΊ 2
  3. ؀ڥ 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
  4. ൃදͷಈػ 4

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

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

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

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

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

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

    ࠓ·Ͱແ৚݅ʹ RxSwift ΛબΜͰ͍͕ͨ΋ͬͱ৭ʑࢼ͢΂͖ͩͬ ͨ • ಉ͡Α͏ͳਓ͕͍Δ͔΋͠Εͳ͍͠೔ຊޠͷ৘ใগͳ͍ͷͰൃද͠ Α͏ 10
  11. λʔήοτͱ࠷ऴ໨ඪ 11

  12. λʔήοτ • RxSwift ೿ • ಛʹཧ༝͸ͳ͍͚Ͳ RxSwift ͔͠࢖ͬͨ͜ͱͳ͍೿ • RxSwift

    Α͏ߟ͑ͨΒ೉͍͠ΜͪΌ͏ʁͱࢥͬͯΔ೿ • ͋Δఔ౓ Rx ͕෼͔Δਓ 12
  13. ࠷ऴ໨ඪ Rx ͷϑϨʔϜϫʔΫΛબͿࡍʹ ReactiveSwift Λબ୒ࢶʹೖΕͯཉ͍͠ 13

  14. ͜ͷൃදͷओࢫͱ͸ؔ܎ແ͍͜ͱ • ReactiveExtensions Λ࠾༻͢Δ͔Ͳ͏͔ • ͲΜͳΞʔΩςΫνϟΛ࠾༻͢Δ͔ 14

  15. ReactiveSwift ͷ֓ཁ 15

  16. ߏ੒ 16 for PureSwift ReactiveSwift for Cocoa ReactiveCocoa Dependency Result

  17. ߏ੒ 17 for PureSwift ReactiveSwift for Cocoa ReactiveCocoa Dependency Result

  18. 18 antitypical/Result

  19. 19 ґଘϥΠϒϥϦ͋Δͷʁʢ৺഑ʣ

  20. 20 Result ͸ศརʂ ୯ମͰ΋࢖͍͍ͨ͘Β͍༗༻ ͔ͩΒେৎ෉"

  21. 21 ඪ४ϥΠϒϥϦʹ௥Ճ͢Δϓϩϙʔβϧʂ

  22. ReactiveSwift Λߏ੒͢Δओͳίϯϙʔωϯτ • Signal • SignalProducer • Property • MutableProperty

    • όΠϯσΟϯάԋࢉࢠ • Action 22
  23. 23 ݟ͍ͯ͘

  24. Signal/SignalProducer 24

  25. Signal/SignalProducer ͷ֓ཁ • RxSwift Ͱ͍͏ `Observable` • Hot ͳ Observable

    ͕ Signal • Cold ͳ Observable ͕ SignalProducer 25
  26. Signal 26

  27. Signal<Value, Error: Swift.Error> 27 • Hot ͳ Observable • subscribe

    ͞ΕΔલ͔Βಈ͍͍ͯΔʢ͓͞Β͍ʣ • ΤϥʔΛܕύϥϝʔλͱͯ࣋ͭ͠
  28. ࢖ͬͯΈΔ 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()
  29. ࢖ͬͯΈΔ 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 Λ࡞੒͢Δ
  30. ࢖ͬͯΈΔ 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> ग़ྗ୲౰
  31. ࢖ͬͯΈΔ 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 ೖྗ୲౰
  32. ࢖ͬͯΈΔ 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) ͷ··ʂ
  33. ࢖ͬͯΈΔ 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:) ૬౰ͷॲཧ͸লུͰ͖Δ
  34. ࢖ͬͯΈΔ 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 Λ࡞Γ΍͍͢
  35. ͓͞Β͍ 35 “Signal Λ map ͯ͠΋ Signal ͷ··” Ͱ͋Δ͜ͱͷԿ͕خ͍͠ʁ

  36. 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()
  37. 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
  38. 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 ʹͳΔ
  39. 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 ͞Ε͔ͨ෼͔ΔΑ͏ ϩάΛ࢓ࠐΜͰ͓͘
  40. 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 ͕ੜ੒͞ΕΔ
 ɾϝϞϦͷແବݣ͍
 ɾόάͷݪҼ
 ʹͳΓಘΔ ɹɹɹ
  41. 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 ͕ੜ੒͞ΕΔ
 ɾϝϞϦͷແବݣ͍
 ɾόάͷݪҼ
 ʹͳΓಘΔ ɹɹɹ$࣮ߦ݁Ռ ʹͬ͜Γͯ͠Δ৔߹Ͱ͸ͳ͍
  42. RxSwift ͩͱ • Hot ͔ Cold ͔ਓ͕ؒ஫ҙͯ͠औΓѻΘͳ͚Ε͹ͳΒͳ͍ 42

  43. 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 ͷม׵͸Մೳ͕ͩɾɾɾ
  44. 44 Ұํ ReactiveSwift

  45. 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()
  46. 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 Λ༻ҙ
  47. 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 ͳ··ʂ
  48. 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 ౓͔࣮͠ߦ͞Εͳ͍ ☺
  49. ReactiveSwiftͩͱ • Hot ͔ Cold ͔೰·ͣͱ΋ܕΛݟΕ͹෼͔Δʂ • ಄Λ೰·ͤΔඞཁ͕ͳ͍ʂ • Hot

    ΛΦϖϨʔλͰܨ͍Ͱ΋ Hot ͷ··ʂ 49
  50. 50 ࿩Λগ͠લ·Ͱ໭͠·͢

  51. ʢ࠶ܝʣ࢖ͬͯΈΔ 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:) ૬౰ͷॲཧ͸লུͰ͖Δ
  52. ʢ࠶ܝʣ࢖ͬͯΈΔ 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:) ૬౰ͷॲཧ͸লུͰ͖Δ
  53. 53 ໌ࣔతʹ dispose ͠ͳͯ͘΋͍͍ʁ

  54. 54 ͏Μ

  55. 55 ͏Μ ʢ·͋ঢ়گʹΑΔ͚Ͳʣ

  56. 56 interrupted Πϕϯτൃੜ࣌ʹ dispose ͞ΕΔ

  57. 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()
  58. 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 ͷΠϯελϯε͕ ղ์͞ΕΔͱɾɾɾ
  59. 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` ͢Δલʹ ऴΘͬͪΌͬͨΑͱ͍͏ҙຯ
  60. Signal.Event 60 public enum Event { case value(Value) case failed(Error)

    case completed case interrupted }
  61. Signal.Event 61 public enum Event { case value(Value) case failed(Error)

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

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

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

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

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

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

  68. SignalProducer<Value, Error: Swift.Error> 68 • Cold ͳ Observable • subscribe

    ͞Ε͔ͯΒಈ͘ʢ͓͞Β͍ʣ • ΤϥʔΛܕύϥϝʔλͱͯ࣋ͭ͠
  69. 69 ͍࣋ͬͯΔΠϯλʔϑΣʔε͸΄΅ Signal ͱಉ͡

  70. ࢖ͬͯΈΔ 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 ͷॲཧ͸লུͰ͖Δ
  71. 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
  72. 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 ඇಉظόʔδϣϯ΋࡞ͬͯΈΔ
  73. ඇಉظ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) } } } }
  74. ඇಉظ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ͭ
  75. ඇಉظ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` ͞ΕΔͱΠχγϟϥΠβʹ౉ͨ͠ Ϋϩʔδϟ͕࣮ߦ͞ΕΔ
  76. ඇಉظ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 ΛऔΔ
  77. ඇಉظ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) } } } } ඇಉظॲཧ͕ऴΘͬͨΒ࣮ߦ͞ΕΔ
  78. ඇಉظ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 ͱͦΜͳʹมΘΒͳ͍Ͱ͢ʣ
  79. 79 ͱ͜ΖͰΤϥʔͷछྨ͕ܕϨϕϧͰΘ͔Δ͜ͱͷ ͳʹ͕خ͍͠ʁ

  80. 80 Ͳ͏ͤ localizeDescription ͔͠ ࢖ΘΜ͠ͳʙ

  81. 81 '

  82. ΤϥʔλΠϓͷϝϦοτ • ΤϥʔͷछྨʹԠͯ͡ॲཧΛ੾Γ෼͚͍ͨͱ͖ͳͲ
 →ʮτʔΫϯ੾Εͷ࣌ͷΈ࠶౓ϩάΠϯॲཧΛཪͰߦ͏ʯͱ͔
 
 Τϥʔͷछྨ͕Θ͔Βͳ͍ͱΩϟετ͠ͳ͚Ε͹ͳΒͳ͍ɻ
 ࣮ߦ͢Δ·ͰΩϟετ͕੒ޭ͢Δ͔Ͳ͏͔͸෼͔Βͳ͍… • Τϥʔ͕ى͖ͳ͍͜ͱΛදݱͰ͖Δ
 →

    NoError Λ࢖͏͜ͱͰΤϥʔϋϯυϦϯά͠ͳͯ͘΋͍ ͍ʂͱ͍͏͜ͱ͕Θ͔Δɻ 82 Τϥʔʹؔ͢Δॲཧ͕ίϯύΠϧ࣌ʹอূ͞ΕΔʂ
  83. 83 Signal/SignalProducer ͓͞Β͍

  84. 84 RxSwift ͱൺֱ

  85. ReactiveSwift VS RxSwift 85 ReactiveSwift RxSwift Hot Signal Observable Cold

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

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

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

    Signal Producer Observable Τϥʔͷܕ ෼͔Δ ෼͔ΒΜ disposeΛলུ Ͱ͖Δ Ͱ͖ͳ͍ RxSwiftͱൺ΂ָͯͰ͖Δ ϚχϡΞϧ dispose ΋Ͱ͖Δ
  89. 89 Signal ͱ SignalProducer ͱͰൺֱ

  90. Signal VS SignalProducer 90 Signal SignalProducer Hot/Cold Hot Cold ߪಡ։࢝ͷϝιου

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

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

    observeXXX startXXX ओͳੜ੒ํ๏ Signal.pipe() ৭ʑ͋Δ ߪಡ։࢝͢Δ͝ͱʹ start ͞ΕΔΜͩͳ͊ ͱײ͡ΒΕΔ໋໊
  93. Signal/SignalProducer ͓͠·͍ 93

  94. Property/MutableProperty 94

  95. MutableProperty 95

  96. MutableProperty<Value> 96 • ߪಡՄೳͳ஋Λอ͍࣋ͯ͠Δ • ஋ͷมߋ͸ Signal / SignalProducer ͔ΒߪಡՄೳ

    • ಉظతʹ஋Λऔಘɾઃఆ͢Δ͜ͱ΋Ͱ͖Δ • RxSwift Ͱ͍͏ BehaviorRelay(چVariable) • ໊લ͕Θ͔Γ΍͍͢ • ReactiveSwift ʹఆٛ͞Ε͍ͯΔʢBehaviorRelay ͸ RxCocoaʹఆٛ͞Ε͍ͯΔʣ
  97. ࢖ͬͯΈΔ 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)
  98. ࢖ͬͯΈΔ 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) ॳظԽ
  99. 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 ஋ͷมߋΛߪಡͰ͖Δ ॳظ஋͸ྲྀΕͯ͜ͳ͍
  100. 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 ஋ͷมߋΛߪಡͰ͖Δ ॳظ஋͕ྲྀΕͯདྷΔ
  101. 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 ஋Λಉظతʹ
 औಘɾઃఆͰ͖Δ
  102. Property 102

  103. Property<Value> 103 • ಡΈऔΓઐ༻ • MutableProperty ͱΠϯλʔϑΣʔε͸΄΅ಉ͡ • RxSwift ʹ͸ಉ༷ͷΫϥε͸ଘࡏ͠ͳ͍

    • ֎෦ʹެ։͢Δ࣌ʹศར
  104. ࢖ͬͯΈΔ(1) 104 let mutableState = MutableProperty(State.notLoaded) mutableState.value = .loading let

    state = Property(capturing: mutableState) state.value = .notLoaded
  105. let mutableState = MutableProperty(State.notLoaded) mutableState.value = .loading let state =

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

    Property(capturing: mutableState) state.value = .notLoaded ࢖ͬͯΈΔ(1) 106 mutableProperty Λ Property ʹม׵ ஋͸ৗʹݩͱͳͬͨ mutableProperty ͱಉ͡
  107. 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
  108. ࢖ͬͯΈΔ(2) 108 struct ViewModel { let state: Property<State> private let

    mutableState: MutableProperty<State> init() { self.mutableState = MutableProperty<State>(.notLoaded) self.state = Property(capturing: mutableState) } }
  109. 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 Λ༻ҙ
  110. 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Ͱ͓࣋ͬͯ͘
  111. 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 ͳͷͰ
  112. struct ViewModel { let state: Property<State> private let mutableState: MutableProperty<State>

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

    init() { self.mutableState = MutableProperty<State>(.notLoaded) self.state = Property(capturing: mutableState) } } ࢖ͬͯΈΔ(2) 113 ͍ͭ͜΋มΘΔ
  114. ͪΐͬͱ·ͱΊ • Property ͸ಡΈऔΓઐ༻ • MutableProperty ͸ಡΈॻ͖Մೳ • ͦΕҎ֎ͷΠϯλʔϑΣʔε͸΄΅ಉ͡ 114

  115. 115 Property/MutableProperty ͷ map ͕ศར

  116. 116 ʮϢʔβ໊Λ4จࣈҎ্ೖྗ͠ͳ͍ͱ ొ࿥Ϙλϯ͕ΞΫςΟϒʹͳΒͳ͍ը໘ʯ ͷ ViewModel

  117. 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 } } }
  118. 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 } } } ೖྗதͷϢʔβʔ໊ ͜͜ʹόΠϯυͯ͠΄͍͠
  119. 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 } } } ੾Γସ͑ϩδοΫ͸Ӆṭ͍ͨͨ͠Ί ಡΈऔΓઐ༻ʹͯ͠Δ
  120. 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ϝιουΛ࢖͑͹ΑΓએݴతʹ͔͚Δ
  121. 121 BehaviorRelayʹ΋ mapϝιου͸͋Δ͕ɾɾɾ

  122. 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 }
  123. 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>
  124. 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>
  125. 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>
  126. 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 ޙͷܕ͕ҧ͏͕ಡΈऔΓઐ༻ʹ͍͔ͨ͠Βʁ ͜ΕͰࠔΔ͜ͱ͸͋Μ·Γແ͍ Ή͠Ζ͋Γ͕͍ͨ
  127. 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>
  128. 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ʹͳΔ
 ͜Ε͸Α͘෼͔Βͳ͍
  129. 129 BehaviorRelayʹ΋ mapϝιου͸͋Δ͕ Observable ʹͳͬͯ͠·͏

  130. 130 ͦͷͨΊಉظతʹ஋ΛऔΕͳ͍ → BehaviorRelay.value ʹΞΫηεͰ͖ͳ͍ʂ

  131. 131 Property/MutableProperty ͓͞Β͍

  132. 132 RxSwift ͱൺֱ

  133. ReactiveSwift VS RxSwift 133 ReactiveSwift RxSwift ಡΈॻ͖Մೳ MutableProperty BehaviorRelay ಡΈऔΓઐ༻

    Property - ଐ͢ΔϑϨʔϜϫʔΫ ReactiveSwift RxCocoa
  134. ReactiveSwift VS RxSwift 134 ReactiveSwift RxSwift ಡΈॻ͖Մೳ MutableProperty BehaviorRelay ಡΈऔΓઐ༻

    Property - ଐ͢ΔϑϨʔϜϫʔΫ ReactiveSwift RxCocoa ଘࡏ͠ͳ͍
  135. 135 PropertyͱMutablePropertyͱͰൺֱ

  136. Property VS MutableProperty 136 Property MutableProperty ಡΈऔΓ ◯ ◯ ॻ͖ࠐΈ

    × ◯ mapޙͷܕ Property Property
  137. Property/MutableProperty ͓͠·͍ 137

  138. <~ όΠϯσΟϯάԋࢉࢠ 138

  139. όΠϯσΟϯάԋࢉࢠ(<~) • ஋ͷόΠϯυʹ࢖͏ • ͪΐͬͱ໘ന͍ 139

  140. ࢖ͬͯΈΔ 140 viewModel.userName <~ textField.reactive.continuousTextValues.map { $0 ?? "" }

    registerButton.reactive.isEnabled <~ viewModel.isEnabled
  141. viewModel.userName <~ textField.reactive.continuousTextValues.map { $0 ?? "" } registerButton.reactive.isEnabled <~

    viewModel.isEnabled ࢖ͬͯΈΔ 141 ͍ͭ͜
  142. viewModel.userName <~ textField.reactive.continuousTextValues.map { $0 ?? "" } registerButton.reactive.isEnabled <~

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

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

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

  146. // ࣮͸ӅΕ͍ͯͨ let disposable = registerButton.reactive.isEnabled <~ viewModel.isEnabled ࢖ͬͯΈΔ 146

    ԋࢉࢠͷ݁Ռ͸ @discardableResult ͳ Disposable Signal/SignalProducer ͱಉ༷ dispose ͷॲཧΛলུͰ͖Δ
  147. όΠϯσΟϯάԋࢉࢠ(<~)͓͞Β͍ • ࠨล͸όΠϯυ͞ΕΔଆ • ӈล͸όΠϯυ͢Δଆ • ฦΓ஋͸ @discardableResult ͳ Disposable

    • dispose ͸লུՄೳ 147
  148. <~ όΠϯσΟϯάԋࢉࢠ ͓͠·͍ 148

  149. Action 149

  150. Action<Input, Output, Error> • ໋໊͕ͬ͘͟Γ • ཧղ͢Δͷʹ͕͔͔࣌ؒΔ • ඇಉظॲཧͷ࣮ߦΛ੍ޚɾ؂ࢹͯ͘͠ΕΔ •

    Input Λ༩͑ͯ Output ΋͘͠͸ Error Λ͸͖ͩ͢ 150
  151. Action<Input, Output, Error> • ໋໊͕ͬ͘͟Γ • ཧղ͢Δͷʹ͕͔͔࣌ؒΔ • ඇಉظॲཧͷ࣮ߦΛ੍ޚɾ؂ࢹͯ͘͠ΕΔ •

    Input Λ༩͑ͯ Output ΋͘͠͸ Error Λ͸͖ͩ͢ 151
  152. 152 Action<Input, Output, Error>

  153. 153 Action<Input, Output, Error> InputΛ༩͑ͯ

  154. 154 Action<Input, Output, Error> Output΋͘͠͸

  155. 155 Action<Input, Output, Error> ErrorΛ͸͖ͩ͢

  156. 156 Ϣʔβʔ໊ͰϢʔβʔҰཡΛ ඇಉظͰݕࡧ͢Δ Action

  157. ࢖ͬͯΈΔ 157 let action = Action<String, [User], APIError> { keyword

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

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

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

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

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

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

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

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

    -> SignalProducer<[User], APIError> in repository.fetchUsers(name: keyword) } action.apply("fenrir").start() apply → start ͞ΕΔͱ ΠχγϟϥΠβʹ౉ͨ͠Ϋϩʔδϟ͕࣮ߦ͞ΕΔ ͜ͷΫϩʔδϟͷ໭Γ஋ͷ SignalProducer ͕ start͞ΕΔ
  166. ࢖ͬͯΈΔ 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`͔ΒऔಘͰ͖Δ
  167. ࢖ͬͯΈΔ 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`͔ΒऔಘͰ͖Δ
  168. ࢖ͬͯΈΔ 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) }
  169. ࢖ͬͯΈΔ 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) }
  170. ࢖ͬͯΈΔ 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
  171. ࢖ͬͯΈΔ 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 ʹͳΔ
  172. ࢖ͬͯΈΔ 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 Πϯδέʔλͷදࣔ੾Γସ͑ͱόΠϯυ͢Δͱ͖ʹศར
  173. ࢖ͬͯΈΔ 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()
  174. ࢖ͬͯΈΔ 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ͭ·Ͱ ͢Ͱʹ࣮ߦதͳΒແࢹ͞ΕΔ
  175. ࢖ͬͯΈΔ 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
  176. ࢖ͬͯΈΔ 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 ࣮ߦՄೳ͔Ͳ͏͔ΛόΠϯσΟϯά
  177. ࢖ͬͯΈΔ 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) } }
  178. ࢖ͬͯΈΔ 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) } } ݸผʹϋϯυϦϯά͢Δ͜ͱ΋Ͱ͖Δ ݸผʹϋϯυϦϯά͠ͳ͍ύλʔϯ ݸผʹϋϯυϦϯά͢Δύλʔϯ
  179. ࢖ͬͯΈΔ 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) } } ࣮ߦͰ͖ͨ ݁Ռ͸੒ޭͩͬͨ
  180. ࢖ͬͯΈΔ 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) } } ࣮ߦෆՄͷঢ়ଶͩͬͨ
  181. ࢖ͬͯΈΔ 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) } } ࣮ߦͰ͖ͨ ݁Ռ͸ࣦഊͩͬͨ
  182. Action͸ͲΜͳ࣌ʹ࢖͑ͦ͏͔ 182 1. Ϙλϯλοϓ 2. API ௨৴ 3. ௨৴த͸ΠϯδέʔλΛදࣔ 4.

    ੒ޭ࣌: ը໘ભҠ
 ࣦഊ࣌: ΞϥʔτΛදࣔ 5. ͨͩ͠λοϓ࿈ଧͳͲͰ௨৴͕ೋॏʹ૸Βͳ͍Α͏ʹ੍ޚ͢Δ Α͋͘Δύλʔϯʹ࢖͑ͦ͏ʂ
  183. Action͸Ԟ͕ਂ͍ • StateΛ༩͑ͨΓ • StateʹԠ࣮ͯ͡ߦͨ͠Γ͠ͳ͔ͬͨΓ 183 ৭ʑͰ͖Δʂ
 ৄ͘͠͸υΩϡϝϯτ or ιʔείʔυಡ΋͏ʂ

  184. Action ͓͞Β͍ • ࣮ߦத͔Ͳ͏͔ͷϑϥάΛ Property<Bool> ͰऔΕΔ • ࣮ߦՄೳ͔Ͳ͏͔ͷϑϥάΛ Property<Bool> ͰऔΕΔ

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

  186. ·ͱΊ 186

  187. ReactiveSwift·ͱΊ • ܕϨϕϧͰ Hot/Cold, Error ͷछྨͱ༗ແ͕൑அͰ͖Δ
 ܕʹݫ͍͠ Swift Β͍͠ϓϩάϥϛϯά͕Ͱ͖Δ •

    ొ৔͢ΔΫϥε͕গͳ͍ͷͰγϯϓϧ 187
  188. ࠓճ࿩ͤͳ͔ͬͨ͜ͱ • BindingTarget • ReactiveCocoaपΓͷ࿩ • RxSwiftͷίϨ͸ReactiveSwiftͰ͸͜͏ॻ͘Αͱ͍͏࿩ • ΋ͬͱ࣮ફతͳ಺༰ 188

  189. 189 ࠷ऴ໨ඪͳΜ΍͚ͬʁ

  190. ࠷ऴ໨ඪ Rx ͷϑϨʔϜϫʔΫΛબͿࡍʹ ReactiveSwift Λબ୒ࢶʹೖΕͯཉ͍͠ 190

  191. 191 ͝ݕ౼͍ͩ͘͞(