Slide 1

Slide 1 text

ೖ໳ ReactiveSwift XFE

Slide 2

Slide 2 text

΋͘͡ •ൃදͷಈػ •λʔήοτͱ࠷ऴ໨ඪ •ReactiveSwift ͷ֓ཁ •Signal / SignalProducer •Property / MutableProperty •όΠϯσΟϯάԋࢉࢠ •Action •·ͱΊ 2

Slide 3

Slide 3 text

؀ڥ 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

Slide 4

Slide 4 text

ൃදͷಈػ 4

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

λʔήοτͱ࠷ऴ໨ඪ 11

Slide 12

Slide 12 text

λʔήοτ • RxSwift ೿ • ಛʹཧ༝͸ͳ͍͚Ͳ RxSwift ͔͠࢖ͬͨ͜ͱͳ͍೿ • RxSwift Α͏ߟ͑ͨΒ೉͍͠ΜͪΌ͏ʁͱࢥͬͯΔ೿ • ͋Δఔ౓ Rx ͕෼͔Δਓ 12

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

ReactiveSwift ͷ֓ཁ 15

Slide 16

Slide 16 text

ߏ੒ 16 for PureSwift ReactiveSwift for Cocoa ReactiveCocoa Dependency Result

Slide 17

Slide 17 text

ߏ੒ 17 for PureSwift ReactiveSwift for Cocoa ReactiveCocoa Dependency Result

Slide 18

Slide 18 text

18 antitypical/Result

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

ReactiveSwift Λߏ੒͢Δओͳίϯϙʔωϯτ • Signal • SignalProducer • Property • MutableProperty • όΠϯσΟϯάԋࢉࢠ • Action 22

Slide 23

Slide 23 text

23 ݟ͍ͯ͘

Slide 24

Slide 24 text

Signal/SignalProducer 24

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

Signal 26

Slide 27

Slide 27 text

Signal 27 • Hot ͳ Observable • subscribe ͞ΕΔલ͔Βಈ͍͍ͯΔʢ͓͞Β͍ʣ • ΤϥʔΛܕύϥϝʔλͱͯ࣋ͭ͠

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

࢖ͬͯΈΔ 32 let (users, observer) = Signal.pipe() let userNames: Signal = 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) ͷ··ʂ

Slide 33

Slide 33 text

࢖ͬͯΈΔ 33 let (users, observer) = Signal.pipe() let userNames: Signal = 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:) ૬౰ͷॲཧ͸লུͰ͖Δ

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

͓͞Β͍ 35 “Signal Λ map ͯ͠΋ Signal ͷ··” Ͱ͋Δ͜ͱͷԿ͕خ͍͠ʁ

Slide 36

Slide 36 text

RxSwift ͩͱ 36 let subject = PublishSubject() 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()

Slide 37

Slide 37 text

RxSwift ͩͱ 37 let subject = PublishSubject() 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

Slide 38

Slide 38 text

RxSwift ͩͱ 38 let subject = PublishSubject() 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 ʹͳΔ

Slide 39

Slide 39 text

RxSwift ͩͱ 39 let subject = PublishSubject() 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 ͞Ε͔ͨ෼͔ΔΑ͏ ϩάΛ࢓ࠐΜͰ͓͘

Slide 40

Slide 40 text

RxSwift ͩͱ 40 let subject = PublishSubject() 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 ͕ੜ੒͞ΕΔ
 ɾϝϞϦͷແବݣ͍
 ɾόάͷݪҼ
 ʹͳΓಘΔ ɹɹɹ

Slide 41

Slide 41 text

RxSwift ͩͱ 41 let subject = PublishSubject() 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 ͕ੜ੒͞ΕΔ
 ɾϝϞϦͷແବݣ͍
 ɾόάͷݪҼ
 ʹͳΓಘΔ ɹɹɹ$࣮ߦ݁Ռ ʹͬ͜Γͯ͠Δ৔߹Ͱ͸ͳ͍

Slide 42

Slide 42 text

RxSwift ͩͱ • Hot ͔ Cold ͔ਓ͕ؒ஫ҙͯ͠औΓѻΘͳ͚Ε͹ͳΒͳ͍ 42

Slide 43

Slide 43 text

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 ͷม׵͸Մೳ͕ͩɾɾɾ

Slide 44

Slide 44 text

44 Ұํ ReactiveSwift

Slide 45

Slide 45 text

ReactiveSwiftͩͱ 45 let (users, observer) = Signal.pipe() let userNames: Signal = 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()

Slide 46

Slide 46 text

ReactiveSwiftͩͱ 46 let (users, observer) = Signal.pipe() let userNames: Signal = 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 Λ༻ҙ

Slide 47

Slide 47 text

ReactiveSwiftͩͱ 47 let (users, observer) = Signal.pipe() let userNames: Signal = 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 ͳ··ʂ

Slide 48

Slide 48 text

ReactiveSwiftͩͱ 48 let (users, observer) = Signal.pipe() let userNames: Signal = 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 ౓͔࣮͠ߦ͞Εͳ͍ ☺

Slide 49

Slide 49 text

ReactiveSwiftͩͱ • Hot ͔ Cold ͔೰·ͣͱ΋ܕΛݟΕ͹෼͔Δʂ • ಄Λ೰·ͤΔඞཁ͕ͳ͍ʂ • Hot ΛΦϖϨʔλͰܨ͍Ͱ΋ Hot ͷ··ʂ 49

Slide 50

Slide 50 text

50 ࿩Λগ͠લ·Ͱ໭͠·͢

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

53 ໌ࣔతʹ dispose ͠ͳͯ͘΋͍͍ʁ

Slide 54

Slide 54 text

54 ͏Μ

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

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

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

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

Slide 64

Slide 64 text

Signal.Event 64 public enum Event { case value(Value) case failed(Error) case completed case interrupted } ߪಡ͕Ωϟϯηϧ͞Εͨ͜ͱ ΛૹΔΠϕϯτ ड͚औΔͱdispose͞ΕΔ RxSwift ʹ͸ͳ͍

Slide 65

Slide 65 text

interrupted ʹΑΔ dispose • `interrupted` ͕ى͜Δͱࣗಈతʹ dispose ͞ΕΔ • ͜ΕʹΑΓ RxSwift ͷ disposed(by:) ૬౰ͷॲཧ͕
 লུͰ͖Δʂ • RxSwift ͷ “DisposeBag Λఆٛͯ͠ disposed(by:) ͠ ͯ…” ͱ͍͏͍ͭ΋ॻ͘ΞϨ͕ແ͘ͳΔ 65

Slide 66

Slide 66 text

खಈͰ dispose ΋Ͱ͖ΔΑ 66 // ͖ͬ͞·ͰӅΕͯͨ let disposable = userNames.observeValues { userName in print(userName) } • खಈͰ΋ dispose Ͱ͖Δ • subscribe ܥͷϝιουͷฦΓ஋͕ RxSwift ͱಉ༷ Disposable • @discardableResult ʹͳ͍ͬͯΔͷͰීஈ͸͋·Γ ҙࣝ͠ͳ͍

Slide 67

Slide 67 text

SignalProducer 67

Slide 68

Slide 68 text

SignalProducer 68 • Cold ͳ Observable • subscribe ͞Ε͔ͯΒಈ͘ʢ͓͞Β͍ʣ • ΤϥʔΛܕύϥϝʔλͱͯ࣋ͭ͠

Slide 69

Slide 69 text

69 ͍࣋ͬͯΔΠϯλʔϑΣʔε͸΄΅ Signal ͱಉ͡

Slide 70

Slide 70 text

࢖ͬͯΈΔ 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 ͷॲཧ͸লུͰ͖Δ

Slide 71

Slide 71 text

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

Slide 72

Slide 72 text

RxSwift ͱൺֱͭͭ͠SignalProducerΛ࡞ͬͯΈΔ 72 // subscribe ͞ΕͨΒಉظతʹ1ͭͷ value ͱ completed Λྲྀ͢ SignalProducer(value: 1) // ReactiveSwift Observable.just(1) // RxSwift // subscribe ͞ΕͨΒಉظతʹ error Λྲྀ͢ SignalProducer(error: APIError.network) // ReactiveSwift Observable.error(APIError.network) // RxSwift // subscribe ͞ΕͨΒಉظతʹ completed Λྲྀ͢ SignalProducer.empty // ReactiveSwift Observable.empty() // RxSwift ඇಉظόʔδϣϯ΋࡞ͬͯΈΔ

Slide 73

Slide 73 text

ඇಉظ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) } } } }

Slide 74

Slide 74 text

ඇಉظ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.Observer, Lifetime) -> Void) ΠχγϟϥΠβͷҾ਺͸ΫϩʔδϟΛ1ͭ

Slide 75

Slide 75 text

ඇಉظ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` ͞ΕΔͱΠχγϟϥΠβʹ౉ͨ͠ Ϋϩʔδϟ͕࣮ߦ͞ΕΔ

Slide 76

Slide 76 text

ඇಉظ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 ΛऔΔ

Slide 77

Slide 77 text

ඇಉظ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) } } } } ඇಉظॲཧ͕ऴΘͬͨΒ࣮ߦ͞ΕΔ

Slide 78

Slide 78 text

ඇಉظ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 ͱͦΜͳʹมΘΒͳ͍Ͱ͢ʣ

Slide 79

Slide 79 text

79 ͱ͜ΖͰΤϥʔͷछྨ͕ܕϨϕϧͰΘ͔Δ͜ͱͷ ͳʹ͕خ͍͠ʁ

Slide 80

Slide 80 text

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

Slide 81

Slide 81 text

81 '

Slide 82

Slide 82 text

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

Slide 83

Slide 83 text

83 Signal/SignalProducer ͓͞Β͍

Slide 84

Slide 84 text

84 RxSwift ͱൺֱ

Slide 85

Slide 85 text

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

Slide 86

Slide 86 text

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

Slide 87

Slide 87 text

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

Slide 88

Slide 88 text

ReactiveSwift VS RxSwift 88 ReactiveSwift RxSwift Hot Signal Observable Cold Signal Producer Observable Τϥʔͷܕ ෼͔Δ ෼͔ΒΜ disposeΛলུ Ͱ͖Δ Ͱ͖ͳ͍ RxSwiftͱൺ΂ָͯͰ͖Δ ϚχϡΞϧ dispose ΋Ͱ͖Δ

Slide 89

Slide 89 text

89 Signal ͱ SignalProducer ͱͰൺֱ

Slide 90

Slide 90 text

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

Slide 91

Slide 91 text

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

Slide 92

Slide 92 text

Signal VS SignalProducer 92 Signal SignalProducer Hot/Cold Hot Cold ߪಡ։࢝ͷϝιου observeXXX startXXX ओͳੜ੒ํ๏ Signal.pipe() ৭ʑ͋Δ ߪಡ։࢝͢Δ͝ͱʹ start ͞ΕΔΜͩͳ͊ ͱײ͡ΒΕΔ໋໊

Slide 93

Slide 93 text

Signal/SignalProducer ͓͠·͍ 93

Slide 94

Slide 94 text

Property/MutableProperty 94

Slide 95

Slide 95 text

MutableProperty 95

Slide 96

Slide 96 text

MutableProperty 96 • ߪಡՄೳͳ஋Λอ͍࣋ͯ͠Δ • ஋ͷมߋ͸ Signal / SignalProducer ͔ΒߪಡՄೳ • ಉظతʹ஋Λऔಘɾઃఆ͢Δ͜ͱ΋Ͱ͖Δ • RxSwift Ͱ͍͏ BehaviorRelay(چVariable) • ໊લ͕Θ͔Γ΍͍͢ • ReactiveSwift ʹఆٛ͞Ε͍ͯΔʢBehaviorRelay ͸ RxCocoaʹఆٛ͞Ε͍ͯΔʣ

Slide 97

Slide 97 text

࢖ͬͯΈΔ 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)

Slide 98

Slide 98 text

࢖ͬͯΈΔ 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) ॳظԽ

Slide 99

Slide 99 text

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 ஋ͷมߋΛߪಡͰ͖Δ ॳظ஋͸ྲྀΕͯ͜ͳ͍

Slide 100

Slide 100 text

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 ஋ͷมߋΛߪಡͰ͖Δ ॳظ஋͕ྲྀΕͯདྷΔ

Slide 101

Slide 101 text

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 ஋Λಉظతʹ
 औಘɾઃఆͰ͖Δ

Slide 102

Slide 102 text

Property 102

Slide 103

Slide 103 text

Property 103 • ಡΈऔΓઐ༻ • MutableProperty ͱΠϯλʔϑΣʔε͸΄΅ಉ͡ • RxSwift ʹ͸ಉ༷ͷΫϥε͸ଘࡏ͠ͳ͍ • ֎෦ʹެ։͢Δ࣌ʹศར

Slide 104

Slide 104 text

࢖ͬͯΈΔ(1) 104 let mutableState = MutableProperty(State.notLoaded) mutableState.value = .loading let state = Property(capturing: mutableState) state.value = .notLoaded

Slide 105

Slide 105 text

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

Slide 106

Slide 106 text

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

Slide 107

Slide 107 text

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

Slide 108

Slide 108 text

࢖ͬͯΈΔ(2) 108 struct ViewModel { let state: Property private let mutableState: MutableProperty init() { self.mutableState = MutableProperty(.notLoaded) self.state = Property(capturing: mutableState) } }

Slide 109

Slide 109 text

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

Slide 110

Slide 110 text

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

Slide 111

Slide 111 text

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

Slide 112

Slide 112 text

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

Slide 113

Slide 113 text

struct ViewModel { let state: Property private let mutableState: MutableProperty init() { self.mutableState = MutableProperty(.notLoaded) self.state = Property(capturing: mutableState) } } ࢖ͬͯΈΔ(2) 113 ͍ͭ͜΋มΘΔ

Slide 114

Slide 114 text

ͪΐͬͱ·ͱΊ • Property ͸ಡΈऔΓઐ༻ • MutableProperty ͸ಡΈॻ͖Մೳ • ͦΕҎ֎ͷΠϯλʔϑΣʔε͸΄΅ಉ͡ 114

Slide 115

Slide 115 text

115 Property/MutableProperty ͷ map ͕ศར

Slide 116

Slide 116 text

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

Slide 117

Slide 117 text

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

Slide 118

Slide 118 text

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

Slide 119

Slide 119 text

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

Slide 120

Slide 120 text

Property ͷ map ͕ศར 120 struct ViewModel { let userName: MutableProperty let isEnabled: Property init() { self.userName = MutableProperty("") self.isEnabled = userName.map { userName in userName.count >= 4 } } } userNameͷ஋͕ܾ·Ε͹ isEnabledͷ஋͸Ұҙʹܾ·Δ mapϝιουΛ࢖͑͹ΑΓએݴతʹ͔͚Δ

Slide 121

Slide 121 text

121 BehaviorRelayʹ΋ mapϝιου͸͋Δ͕ɾɾɾ

Slide 122

Slide 122 text

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

Slide 123

Slide 123 text

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

Slide 124

Slide 124 text

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

Slide 125

Slide 125 text

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

Slide 126

Slide 126 text

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

Slide 127

Slide 127 text

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

Slide 128

Slide 128 text

let fenrir = "fenrir" let array: Array = Array(arrayLiteral: fenrir).map { $0.count } let property: Property = Property(value: fenrir).map { $0.count } let mutable: Property = MutableProperty(fenrir).map { $0.count } let relay: Observable = BehaviorRelay(value: fenrir).map { $0.count } Observable ← map ← BehaviorRelay map ޙͷܕ͕ObservableʹͳΔ
 ͜Ε͸Α͘෼͔Βͳ͍

Slide 129

Slide 129 text

129 BehaviorRelayʹ΋ mapϝιου͸͋Δ͕ Observable ʹͳͬͯ͠·͏

Slide 130

Slide 130 text

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

Slide 131

Slide 131 text

131 Property/MutableProperty ͓͞Β͍

Slide 132

Slide 132 text

132 RxSwift ͱൺֱ

Slide 133

Slide 133 text

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

Slide 134

Slide 134 text

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

Slide 135

Slide 135 text

135 PropertyͱMutablePropertyͱͰൺֱ

Slide 136

Slide 136 text

Property VS MutableProperty 136 Property MutableProperty ಡΈऔΓ ◯ ◯ ॻ͖ࠐΈ × ◯ mapޙͷܕ Property Property

Slide 137

Slide 137 text

Property/MutableProperty ͓͠·͍ 137

Slide 138

Slide 138 text

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

Slide 139

Slide 139 text

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

Slide 140

Slide 140 text

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

Slide 141

Slide 141 text

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

Slide 142

Slide 142 text

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

Slide 143

Slide 143 text

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

Slide 144

Slide 144 text

viewModel.userName <~ textField.reactive.continuousTextValues.map { $0 ?? "" } registerButton.reactive.isEnabled <~ viewModel.isEnabled ࢖ͬͯΈΔ 144 ӈล͕ Property/MutableProperty ͷ৔߹͸ݱࡏͷ஋͕ଈྲྀΕͯ͘Δ ஋ͷऔΓಀ͕͠Λߟ͑ͳͯ͘ྑ͍

Slide 145

Slide 145 text

࢖ͬͯΈΔ 145 // ࣮͸ӅΕ͍ͯͨ registerButton.reactive.isEnabled <~ viewModel.isEnabled

Slide 146

Slide 146 text

// ࣮͸ӅΕ͍ͯͨ let disposable = registerButton.reactive.isEnabled <~ viewModel.isEnabled ࢖ͬͯΈΔ 146 ԋࢉࢠͷ݁Ռ͸ @discardableResult ͳ Disposable Signal/SignalProducer ͱಉ༷ dispose ͷॲཧΛলུͰ͖Δ

Slide 147

Slide 147 text

όΠϯσΟϯάԋࢉࢠ(<~)͓͞Β͍ • ࠨล͸όΠϯυ͞ΕΔଆ • ӈล͸όΠϯυ͢Δଆ • ฦΓ஋͸ @discardableResult ͳ Disposable • dispose ͸লུՄೳ 147

Slide 148

Slide 148 text

<~ όΠϯσΟϯάԋࢉࢠ ͓͠·͍ 148

Slide 149

Slide 149 text

Action 149

Slide 150

Slide 150 text

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

Slide 151

Slide 151 text

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

Slide 152

Slide 152 text

152 Action

Slide 153

Slide 153 text

153 Action InputΛ༩͑ͯ

Slide 154

Slide 154 text

154 Action Output΋͘͠͸

Slide 155

Slide 155 text

155 Action ErrorΛ͸͖ͩ͢

Slide 156

Slide 156 text

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

Slide 157

Slide 157 text

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

Slide 158

Slide 158 text

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

Slide 159

Slide 159 text

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

Slide 160

Slide 160 text

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

Slide 161

Slide 161 text

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

Slide 162

Slide 162 text

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

Slide 163

Slide 163 text

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

Slide 164

Slide 164 text

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

Slide 165

Slide 165 text

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

Slide 166

Slide 166 text

࢖ͬͯΈΔ 166 let action = Action { 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`͔ΒऔಘͰ͖Δ

Slide 167

Slide 167 text

࢖ͬͯΈΔ 167 let action = Action { 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`͔ΒऔಘͰ͖Δ

Slide 168

Slide 168 text

࢖ͬͯΈΔ 168 let action = Action { 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) }

Slide 169

Slide 169 text

࢖ͬͯΈΔ 169 let action = Action { 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) }

Slide 170

Slide 170 text

࢖ͬͯΈΔ 170 let action = Action { 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

Slide 171

Slide 171 text

࢖ͬͯΈΔ 171 let action = Action { 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 action ͕࣮ߦ͍ͯ͠ΔؒͷΈ true ʹͳΔ

Slide 172

Slide 172 text

࢖ͬͯΈΔ 172 let action = Action { 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 Πϯδέʔλͷදࣔ੾Γସ͑ͱόΠϯυ͢Δͱ͖ʹศར

Slide 173

Slide 173 text

࢖ͬͯΈΔ 173 let action = Action { 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()

Slide 174

Slide 174 text

࢖ͬͯΈΔ 174 let action = Action { 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ͭ·Ͱ ͢Ͱʹ࣮ߦதͳΒແࢹ͞ΕΔ

Slide 175

Slide 175 text

࢖ͬͯΈΔ 175 let action = Action { 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

Slide 176

Slide 176 text

࢖ͬͯΈΔ 176 let action = Action { 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 ࣮ߦՄೳ͔Ͳ͏͔ΛόΠϯσΟϯά

Slide 177

Slide 177 text

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

Slide 178

Slide 178 text

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

Slide 179

Slide 179 text

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

Slide 180

Slide 180 text

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

Slide 181

Slide 181 text

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

Slide 182

Slide 182 text

Action͸ͲΜͳ࣌ʹ࢖͑ͦ͏͔ 182 1. Ϙλϯλοϓ 2. API ௨৴ 3. ௨৴த͸ΠϯδέʔλΛදࣔ 4. ੒ޭ࣌: ը໘ભҠ
 ࣦഊ࣌: ΞϥʔτΛදࣔ 5. ͨͩ͠λοϓ࿈ଧͳͲͰ௨৴͕ೋॏʹ૸Βͳ͍Α͏ʹ੍ޚ͢Δ Α͋͘Δύλʔϯʹ࢖͑ͦ͏ʂ

Slide 183

Slide 183 text

Action͸Ԟ͕ਂ͍ • StateΛ༩͑ͨΓ • StateʹԠ࣮ͯ͡ߦͨ͠Γ͠ͳ͔ͬͨΓ 183 ৭ʑͰ͖Δʂ
 ৄ͘͠͸υΩϡϝϯτ or ιʔείʔυಡ΋͏ʂ

Slide 184

Slide 184 text

Action ͓͞Β͍ • ࣮ߦத͔Ͳ͏͔ͷϑϥάΛ Property ͰऔΕΔ • ࣮ߦՄೳ͔Ͳ͏͔ͷϑϥάΛ Property ͰऔΕΔ • 1౓ʹ࣮ߦͰ͖Δඇಉظॲཧ͸1ͭ·Ͱ • APIݺͼग़͠ͱ૬ੑ͕͍͍ • ֶशίετߴ͍ 184

Slide 185

Slide 185 text

Action ͓͠·͍ 185

Slide 186

Slide 186 text

·ͱΊ 186

Slide 187

Slide 187 text

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

Slide 188

Slide 188 text

ࠓճ࿩ͤͳ͔ͬͨ͜ͱ • BindingTarget • ReactiveCocoaपΓͷ࿩ • RxSwiftͷίϨ͸ReactiveSwiftͰ͸͜͏ॻ͘Αͱ͍͏࿩ • ΋ͬͱ࣮ફతͳ಺༰ 188

Slide 189

Slide 189 text

189 ࠷ऴ໨ඪͳΜ΍͚ͬʁ

Slide 190

Slide 190 text

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

Slide 191

Slide 191 text

191 ͝ݕ౼͍ͩ͘͞(