Share
Embed
入門 ReactiveSwift / Introduction to ReactiveSwift
Studio Rookery
November 22, 2018
Transcript
191 slides
-
͘͡ •ൃදͷಈػ •λʔήοτͱ࠷ऴඪ •ReactiveSwift ͷ֓ཁ •Signal / SignalProducer •Property /
MutableProperty •όΠϯσΟϯάԋࢉࢠ •Action •·ͱΊ 2 -
ڥ 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 -
ൃදͷಈػ • RxSwiftΛ1͘Β͍ͬͯͨ • ͍͜ͳ͖͕ͤͯͨͦΕͱಉ࣌ʹෆຬग़͖ͯͨ • ReactiveSwiftͷ͜ͱ͕ؾʹͳ͖ͬͯͨ • ReactiveSwiftͬͯΈͨΒͱͯศརͩͬͨ •
ࠓ·Ͱແ݅ʹ RxSwift ΛબΜͰ͍͕ͨͬͱ৭ʑࢼ͖ͩͬ͢ ͨ • ಉ͡Α͏ͳਓ͕͍Δ͔͠Εͳ͍͠ຊޠͷใগͳ͍ͷͰൃද͠ Α͏ 5 -
ൃදͷಈػ • RxSwiftΛ1͘Β͍ͬͯͨ • ͍͜ͳ͖͕ͤͯͨͦΕͱಉ࣌ʹෆຬग़͖ͯͨ • ReactiveSwiftͷ͜ͱ͕ؾʹͳ͖ͬͯͨ • ReactiveSwiftͬͯΈͨΒͱͯศརͩͬͨ •
ࠓ·Ͱແ݅ʹ RxSwift ΛબΜͰ͍͕ͨͬͱ৭ʑࢼ͖ͩͬ͢ ͨ • ಉ͡Α͏ͳਓ͕͍Δ͔͠Εͳ͍͠ຊޠͷใগͳ͍ͷͰൃද͠ Α͏ 6 -
ൃදͷಈػ • RxSwiftΛ1͘Β͍ͬͯͨ • ͍͜ͳ͖͕ͤͯͨͦΕͱಉ࣌ʹෆຬग़͖ͯͨ • ReactiveSwiftͷ͜ͱ͕ؾʹͳ͖ͬͯͨ • ReactiveSwiftͬͯΈͨΒͱͯศརͩͬͨ •
ࠓ·Ͱແ݅ʹ RxSwift ΛબΜͰ͍͕ͨͬͱ৭ʑࢼ͖ͩͬ͢ ͨ • ಉ͡Α͏ͳਓ͕͍Δ͔͠Εͳ͍͠ຊޠͷใগͳ͍ͷͰൃද͠ Α͏ 7 -
ൃදͷಈػ • RxSwiftΛ1͘Β͍ͬͯͨ • ͍͜ͳ͖͕ͤͯͨͦΕͱಉ࣌ʹෆຬग़͖ͯͨ • ReactiveSwiftͷ͜ͱ͕ؾʹͳ͖ͬͯͨ • ReactiveSwiftͬͯΈͨΒͱͯศརͩͬͨ •
ࠓ·Ͱແ݅ʹ RxSwift ΛબΜͰ͍͕ͨͬͱ৭ʑࢼ͖ͩͬ͢ ͨ • ಉ͡Α͏ͳਓ͕͍Δ͔͠Εͳ͍͠ຊޠͷใগͳ͍ͷͰൃද͠ Α͏ 8 -
ൃදͷಈػ • RxSwiftΛ1͘Β͍ͬͯͨ • ͍͜ͳ͖͕ͤͯͨͦΕͱಉ࣌ʹෆຬग़͖ͯͨ • ReactiveSwiftͷ͜ͱ͕ؾʹͳ͖ͬͯͨ • ReactiveSwiftͬͯΈͨΒͱͯศརͩͬͨ •
ࠓ·Ͱແ݅ʹ RxSwift ΛબΜͰ͍͕ͨͬͱ৭ʑࢼ͖ͩͬ͢ ͨ • ಉ͡Α͏ͳਓ͕͍Δ͔͠Εͳ͍͠ຊޠͷใগͳ͍ͷͰൃද͠ Α͏ 9 -
ൃදͷಈػ • RxSwiftΛ1͘Β͍ͬͯͨ • ͍͜ͳ͖͕ͤͯͨͦΕͱಉ࣌ʹෆຬग़͖ͯͨ • ReactiveSwiftͷ͜ͱ͕ؾʹͳ͖ͬͯͨ • ReactiveSwiftͬͯΈͨΒͱͯศརͩͬͨ •
ࠓ·Ͱແ݅ʹ RxSwift ΛબΜͰ͍͕ͨͬͱ৭ʑࢼ͖ͩͬ͢ ͨ • ಉ͡Α͏ͳਓ͕͍Δ͔͠Εͳ͍͠ຊޠͷใগͳ͍ͷͰൃද͠ Α͏ 10 -
λʔήοτ • RxSwift • ಛʹཧ༝ͳ͍͚Ͳ RxSwift ͔ͬͨ͜͠ͱͳ͍ • RxSwift
Α͏ߟ͑ͨΒ͍͠ΜͪΌ͏ʁͱࢥͬͯΔ • ͋Δఔ Rx ͕͔Δਓ 12 -
ReactiveSwift Λߏ͢Δओͳίϯϙʔωϯτ • Signal • SignalProducer • Property • MutableProperty
• όΠϯσΟϯάԋࢉࢠ • Action 22 -
Signal/SignalProducer ͷ֓ཁ • RxSwift Ͱ͍͏ `Observable` • Hot ͳ Observable
͕ Signal • Cold ͳ Observable ͕ SignalProducer 25 -
Signal<Value, Error: Swift.Error> 27 • Hot ͳ Observable • subscribe
͞ΕΔલ͔Βಈ͍͍ͯΔʢ͓͞Β͍ʣ • ΤϥʔΛܕύϥϝʔλͱͯ࣋ͭ͠ -
ͬͯΈΔ 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 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 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 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 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 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 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 Λ࡞Γ͍͢ -
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() -
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 -
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 ʹͳΔ -
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 ͞Ε͔͔ͨΔΑ͏ ϩάΛࠐΜͰ͓͘ -
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 ͕ੜ͞ΕΔ ɾϝϞϦͷແବݣ͍ ɾόάͷݪҼ ʹͳΓಘΔ ɹɹɹ -
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 ͕ੜ͞ΕΔ ɾϝϞϦͷແବݣ͍ ɾόάͷݪҼ ʹͳΓಘΔ ɹɹɹ$࣮ߦ݁Ռ ʹͬ͜Γͯ͠Δ߹Ͱͳ͍ -
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 ͷมՄೳ͕ͩɾɾɾ -
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() -
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 Λ༻ҙ -
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 ͳ··ʂ -
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 ͔࣮͠ߦ͞Εͳ͍ ☺ -
ReactiveSwiftͩͱ • Hot ͔ Cold ͔·ͣͱܕΛݟΕ͔Δʂ • ಄Λ·ͤΔඞཁ͕ͳ͍ʂ • Hot
ΛΦϖϨʔλͰܨ͍Ͱ Hot ͷ··ʂ 49 -
ʢ࠶ܝʣͬͯΈΔ 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 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:) ૬ͷॲཧলུͰ͖Δ -
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() -
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 ͷΠϯελϯε͕ ղ์͞ΕΔͱɾɾɾ -
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` ͢Δલʹ ऴΘͬͪΌͬͨΑͱ͍͏ҙຯ -
Signal.Event 60 public enum Event { case value(Value) case failed(Error)
case completed case interrupted } -
Signal.Event 61 public enum Event { case value(Value) case failed(Error)
case completed case interrupted } ΛૹΔΠϕϯτ RxSwift Ͱ next -
Signal.Event 62 public enum Event { case value(Value) case failed(Error)
case completed case interrupted } ࣦഊΛૹΔΠϕϯτ RxSwift Ͱ error ड͚औΔͱdispose͞ΕΔ -
Signal.Event 63 public enum Event { case value(Value) case failed(Error)
case completed case interrupted } ྃΛૹΔΠϕϯτ RxSwift Ͱ completed ड͚औΔͱdispose͞ΕΔ -
Signal.Event 64 public enum Event { case value(Value) case failed(Error)
case completed case interrupted } ߪಡ͕Ωϟϯηϧ͞Εͨ͜ͱ ΛૹΔΠϕϯτ ड͚औΔͱdispose͞ΕΔ RxSwift ʹͳ͍ -
interrupted ʹΑΔ dispose • `interrupted` ͕ى͜Δͱࣗಈతʹ dispose ͞ΕΔ • ͜ΕʹΑΓ
RxSwift ͷ disposed(by:) ૬ͷॲཧ͕ লུͰ͖Δʂ • RxSwift ͷ “DisposeBag Λఆٛͯ͠ disposed(by:) ͠ ͯ…” ͱ͍͏͍ͭॻ͘ΞϨ͕ແ͘ͳΔ 65 -
खಈͰ dispose Ͱ͖ΔΑ 66 // ͖ͬ͞·ͰӅΕͯͨ let disposable = userNames.observeValues
{ userName in print(userName) } • खಈͰ dispose Ͱ͖Δ • subscribe ܥͷϝιουͷฦΓ͕ RxSwift ͱಉ༷ Disposable • @discardableResult ʹͳ͍ͬͯΔͷͰීஈ͋·Γ ҙࣝ͠ͳ͍ -
SignalProducer<Value, Error: Swift.Error> 68 • Cold ͳ Observable • subscribe
͞Ε͔ͯΒಈ͘ʢ͓͞Β͍ʣ • ΤϥʔΛܕύϥϝʔλͱͯ࣋ͭ͠ -
ͬͯΈΔ 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 ͷॲཧলུͰ͖Δ -
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 -
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 ඇಉظόʔδϣϯ࡞ͬͯΈΔ -
ඇಉظ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) } } } } -
ඇಉظ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ͭ -
ඇಉظ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` ͞ΕΔͱΠχγϟϥΠβʹͨ͠ Ϋϩʔδϟ͕࣮ߦ͞ΕΔ -
ඇಉظ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 ΛऔΔ -
ඇಉظ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) } } } } ඇಉظॲཧ͕ऴΘͬͨΒ࣮ߦ͞ΕΔ -
ඇಉظ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 ͱͦΜͳʹมΘΒͳ͍Ͱ͢ʣ -
ΤϥʔλΠϓͷϝϦοτ • ΤϥʔͷछྨʹԠͯ͡ॲཧΛΓ͚͍ͨͱ͖ͳͲ →ʮτʔΫϯΕͷ࣌ͷΈ࠶ϩάΠϯॲཧΛཪͰߦ͏ʯͱ͔ Τϥʔͷछྨ͕Θ͔Βͳ͍ͱΩϟετ͠ͳ͚ΕͳΒͳ͍ɻ ࣮ߦ͢Δ·ͰΩϟετ͕ޭ͢Δ͔Ͳ͏͔͔Βͳ͍… • Τϥʔ͕ى͖ͳ͍͜ͱΛදݱͰ͖Δ →
NoError Λ͏͜ͱͰΤϥʔϋϯυϦϯά͠ͳ͍ͯ͘ ͍ʂͱ͍͏͜ͱ͕Θ͔Δɻ 82 Τϥʔʹؔ͢Δॲཧ͕ίϯύΠϧ࣌ʹอূ͞ΕΔʂ -
ReactiveSwift VS RxSwift 85 ReactiveSwift RxSwift Hot Signal Observable Cold
Signal Producer Observable Τϥʔͷܕ ͔Δ ͔ΒΜ disposeΛলུ Ͱ͖Δ Ͱ͖ͳ͍ -
ReactiveSwift VS RxSwift 86 ReactiveSwift RxSwift Hot Signal Observable Cold
Signal Producer Observable Τϥʔͷܕ ͔Δ ͔ΒΜ disposeΛলུ Ͱ͖Δ Ͱ͖ͳ͍ ܕϨϕϧͰ Hot ͔ Cold ͷ۠ผ͕ͭ͘ -
ReactiveSwift VS RxSwift 87 ReactiveSwift RxSwift Hot Signal Observable Cold
Signal Producer Observable Τϥʔͷܕ ͔Δ ͔ΒΜ disposeΛলུ Ͱ͖Δ Ͱ͖ͳ͍ ܕϨϕϧͰΤϥʔͷछྨͷ۠ผ͕ͭ͘ `NoError`Λ͑Τϥʔ͕ى͖ͳ͍͜ͱΛදݱͰ͖Δ -
ReactiveSwift VS RxSwift 88 ReactiveSwift RxSwift Hot Signal Observable Cold
Signal Producer Observable Τϥʔͷܕ ͔Δ ͔ΒΜ disposeΛলུ Ͱ͖Δ Ͱ͖ͳ͍ RxSwiftͱൺָͯͰ͖Δ ϚχϡΞϧ dispose Ͱ͖Δ -
Signal VS SignalProducer 90 Signal SignalProducer Hot/Cold Hot Cold ߪಡ։࢝ͷϝιου
observeXXX startXXX ओͳੜํ๏ Signal.pipe() ৭ʑ͋Δ -
Signal VS SignalProducer 91 Signal SignalProducer Hot/Cold Hot Cold ߪಡ։࢝ͷϝιου
observeXXX startXXX ओͳੜํ๏ Signal.pipe() ৭ʑ͋Δ ໋໊ͷҧ͍͕྆ऀͷҧ͍ΛࡍཱͨͤͯΔʢͱࢥ͏ʣ -
Signal VS SignalProducer 92 Signal SignalProducer Hot/Cold Hot Cold ߪಡ։࢝ͷϝιου
observeXXX startXXX ओͳੜํ๏ Signal.pipe() ৭ʑ͋Δ ߪಡ։࢝͢Δ͝ͱʹ start ͞ΕΔΜͩͳ͊ ͱײ͡ΒΕΔ໋໊ -
MutableProperty<Value> 96 • ߪಡՄೳͳΛอ͍࣋ͯ͠Δ • ͷมߋ Signal / SignalProducer ͔ΒߪಡՄೳ
• ಉظతʹΛऔಘɾઃఆ͢Δ͜ͱͰ͖Δ • RxSwift Ͱ͍͏ BehaviorRelay(چVariable) • ໊લ͕Θ͔Γ͍͢ • ReactiveSwift ʹఆٛ͞Ε͍ͯΔʢBehaviorRelay RxCocoaʹఆٛ͞Ε͍ͯΔʣ -
ͬͯΈΔ 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 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) ॳظԽ -
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) ͬͯΈΔ 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) ͬͯΈΔ 101 Λಉظతʹ औಘɾઃఆͰ͖Δ -
ͬͯΈΔ(1) 104 let mutableState = MutableProperty(State.notLoaded) mutableState.value = .loading let
state = Property(capturing: mutableState) state.value = .notLoaded -
let mutableState = MutableProperty(State.notLoaded) mutableState.value = .loading let state =
Property(capturing: mutableState) state.value = .notLoaded ͬͯΈΔ(1) 105 લड़ͷ௨ΓMutableProperty Λߋ৽Ͱ͖Δ -
let mutableState = MutableProperty(State.notLoaded) mutableState.value = .loading let state =
Property(capturing: mutableState) state.value = .notLoaded ͬͯΈΔ(1) 106 mutableProperty Λ Property ʹม ৗʹݩͱͳͬͨ mutableProperty ͱಉ͡ -
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 -
ͬͯΈΔ(2) 108 struct ViewModel { let state: Property<State> private let
mutableState: MutableProperty<State> init() { self.mutableState = MutableProperty<State>(.notLoaded) self.state = Property(capturing: mutableState) } } -
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 Λ༻ҙ -
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Ͱ͓࣋ͬͯ͘ -
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 ͳͷͰ -
struct ViewModel { let state: Property<State> private let mutableState: MutableProperty<State>
init() { self.mutableState = MutableProperty<State>(.notLoaded) self.state = Property(capturing: mutableState) } } ͬͯΈΔ(2) 112 ͍ͭ͜Λม͑Δͱ -
struct ViewModel { let state: Property<State> private let mutableState: MutableProperty<State>
init() { self.mutableState = MutableProperty<State>(.notLoaded) self.state = Property(capturing: mutableState) } } ͬͯΈΔ(2) 113 ͍ͭ͜มΘΔ -
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 } } } -
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 } } } ೖྗதͷϢʔβʔ໊ ͜͜ʹόΠϯυͯ͠΄͍͠ -
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 } } } Γସ͑ϩδοΫӅṭ͍ͨͨ͠Ί ಡΈऔΓઐ༻ʹͯ͠Δ -
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ϝιουΛ͑ΑΓએݴతʹ͔͚Δ -
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 } -
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> -
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> -
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> -
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 ޙͷܕ͕ҧ͏͕ಡΈऔΓઐ༻ʹ͍͔ͨ͠Βʁ ͜ΕͰࠔΔ͜ͱ͋Μ·Γແ͍ Ή͠Ζ͋Γ͕͍ͨ -
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> -
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ʹͳΔ ͜ΕΑ͔͘Βͳ͍ -
ReactiveSwift VS RxSwift 133 ReactiveSwift RxSwift ಡΈॻ͖Մೳ MutableProperty BehaviorRelay ಡΈऔΓઐ༻
Property - ଐ͢ΔϑϨʔϜϫʔΫ ReactiveSwift RxCocoa -
ReactiveSwift VS RxSwift 134 ReactiveSwift RxSwift ಡΈॻ͖Մೳ MutableProperty BehaviorRelay ಡΈऔΓઐ༻
Property - ଐ͢ΔϑϨʔϜϫʔΫ ReactiveSwift RxCocoa ଘࡏ͠ͳ͍ -
Property VS MutableProperty 136 Property MutableProperty ಡΈऔΓ ◯ ◯ ॻ͖ࠐΈ
× ◯ mapޙͷܕ Property Property -
ͬͯΈΔ 140 viewModel.userName <~ textField.reactive.continuousTextValues.map { $0 ?? "" }
registerButton.reactive.isEnabled <~ viewModel.isEnabled -
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 ͬͯΈΔ 142 ࠨลʹόΠϯυ͞ΕΔଆΛஔ͘ ɾMutableProperty ɾBindingTarget ͳͲ -
viewModel.userName <~ textField.reactive.continuousTextValues.map { $0 ?? "" } registerButton.reactive.isEnabled <~
viewModel.isEnabled ͬͯΈΔ 143 ӈลʹΛૹΔଆΛஔ͘ ɾSignal/SignalProducer ɾProperty/MutableProperty ͳͲ -
viewModel.userName <~ textField.reactive.continuousTextValues.map { $0 ?? "" } registerButton.reactive.isEnabled <~
viewModel.isEnabled ͬͯΈΔ 144 ӈล͕ Property/MutableProperty ͷ߹ݱࡏͷ͕ଈྲྀΕͯ͘Δ ͷऔΓಀ͕͠Λߟ͑ͳͯ͘ྑ͍ -
// ࣮ӅΕ͍ͯͨ let disposable = registerButton.reactive.isEnabled <~ viewModel.isEnabled ͬͯΈΔ 146
ԋࢉࢠͷ݁Ռ @discardableResult ͳ Disposable Signal/SignalProducer ͱಉ༷ dispose ͷॲཧΛলུͰ͖Δ -
Action<Input, Output, Error> • ໋໊͕ͬ͘͟Γ • ཧղ͢Δͷʹ͕͔͔࣌ؒΔ • ඇಉظॲཧͷ࣮ߦΛ੍ޚɾࢹͯ͘͠ΕΔ •
Input Λ༩͑ͯ Output ͘͠ Error Λ͖ͩ͢ 150 -
Action<Input, Output, Error> • ໋໊͕ͬ͘͟Γ • ཧղ͢Δͷʹ͕͔͔࣌ؒΔ • ඇಉظॲཧͷ࣮ߦΛ੍ޚɾࢹͯ͘͠ΕΔ •
Input Λ༩͑ͯ Output ͘͠ Error Λ͖ͩ͢ 151 -
ͬͯΈΔ 157 let action = Action<String, [User], APIError> { keyword
-> SignalProducer<[User], APIError> in repository.fetchUsers(name: keyword) } Input → String (=Ϣʔβʔ໊) Output → [User] (=ϢʔβʔҰཡ) Error → APIError (=Τϥʔ) -
ͬͯΈΔ 158 let action = Action<String, [User], APIError> { keyword
-> SignalProducer<[User], APIError> in repository.fetchUsers(name: keyword) } ΠχγϟϥΠβͷҾΫϩʔδϟ1ͭ ʢଞͷύλʔϯ͋Δʣ -
ͬͯΈΔ 159 let action = Action<String, [User], APIError> { keyword
-> SignalProducer<[User], APIError> in repository.fetchUsers(name: keyword) } (Input) -> SignalProducer<Output, Error> -
ͬͯΈΔ 160 let action = Action<String, [User], APIError> { keyword
-> SignalProducer<[User], APIError> in repository.fetchUsers(name: keyword) } (Input) -> SignalProducer<Output, Error> -
ͬͯΈΔ 161 let action = Action<String, [User], APIError> { keyword
-> SignalProducer<[User], APIError> in repository.fetchUsers(name: keyword) } (Input) -> SignalProducer<Output, Error> -
ͬͯΈΔ 162 let action = Action<String, [User], APIError> { keyword
-> SignalProducer<[User], APIError> in repository.fetchUsers(name: keyword) } (Input) -> SignalProducer<Output, Error> -
ͬͯΈΔ 163 let action = Action<String, [User], APIError> { keyword
-> SignalProducer<[User], APIError> in repository.fetchUsers(name: keyword) } action.apply("fenrir").start() -
ͬͯΈΔ 164 let action = Action<String, [User], APIError> { keyword
-> SignalProducer<[User], APIError> in repository.fetchUsers(name: keyword) } action.apply("fenrir").start() apply ϝιουͰ Input(=String) Λ༩͑Δ -
ͬͯΈΔ 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 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 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 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 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 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 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 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 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 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 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 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 // 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 // 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 // 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 // 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 // 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) } } ࣮ߦͰ͖ͨ ݁Ռࣦഊͩͬͨ -
ActionͲΜͳ࣌ʹ͑ͦ͏͔ 182 1. Ϙλϯλοϓ 2. API ௨৴ 3. ௨৴தΠϯδέʔλΛදࣔ 4.
ޭ࣌: ը໘ભҠ ࣦഊ࣌: ΞϥʔτΛදࣔ 5. ͨͩ͠λοϓ࿈ଧͳͲͰ௨৴͕ೋॏʹΒͳ͍Α͏ʹ੍ޚ͢Δ Α͋͘Δύλʔϯʹ͑ͦ͏ʂ -
Action ͓͞Β͍ • ࣮ߦத͔Ͳ͏͔ͷϑϥάΛ Property<Bool> ͰऔΕΔ • ࣮ߦՄೳ͔Ͳ͏͔ͷϑϥάΛ Property<Bool> ͰऔΕΔ
• 1ʹ࣮ߦͰ͖Δඇಉظॲཧ1ͭ·Ͱ • APIݺͼग़͠ͱ૬ੑ͕͍͍ • ֶशίετߴ͍ 184 -
ReactiveSwift·ͱΊ • ܕϨϕϧͰ Hot/Cold, Error ͷछྨͱ༗ແ͕அͰ͖Δ ܕʹݫ͍͠ Swift Β͍͠ϓϩάϥϛϯά͕Ͱ͖Δ •
ొ͢ΔΫϥε͕গͳ͍ͷͰγϯϓϧ 187