Share
Embed
Reactive Programming Workshop
Slides for Reactive Programming workshop. Reactive Swift. Signals, Signal Producers etc
Paul Taykalo
February 25, 2018
Transcript
63 slides
-
Reactive Programming Workshop by Paul Taykalo, Stanfy 1 — Reactive
Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13 -
Plan → About Reactive Programming → Basics → Reactive Libraries
Differences → Debugging Tooltips → Modifying Code to Reactive → Switching Back from Reactive? 3 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13 -
About Reactive Programming 4 — Reactive Programming Workshop, by Paul
Taykalo, #CocoaHeadsUkraine#13 -
Async vs Sync 5 — Reactive Programming Workshop, by Paul
Taykalo, #CocoaHeadsUkraine#13 -
Everything is a Stream 6 — Reactive Programming Workshop, by
Paul Taykalo, #CocoaHeadsUkraine#13 -
Stream of values over time 7 — Reactive Programming Workshop,
by Paul Taykalo, #CocoaHeadsUkraine#13 -
Stream → Push driven → Can send multiple values →
Can be cancelled → Can complete → Can fail with error → Can be termintated (Ugh) * 8 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13 -
Observable Signal SignalProduc 9 — Reactive Programming Workshop, by Paul
Taykalo, #CocoaHeadsUkraine#13 -
Signal<Value, Error> 10 — Reactive Programming Workshop, by Paul Taykalo,
#CocoaHeadsUkraine#13 -
Signal<Value, Error> 11 — Reactive Programming Workshop, by Paul Taykalo,
#CocoaHeadsUkraine#13 -
Signal Events enum Event<Value, Error> { case value(Value) case failed(Error)
case completed case interrupted } 14 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13 -
Signal Termination enum Event<Value, Error> { case value(Value) case failed(Error)
// ❌ case completed // ❌ case interrupted // ❌ } 15 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13 -
Signal SignalProducer 16 — Reactive Programming Workshop, by Paul Taykalo,
#CocoaHeadsUkraine#13 -
Signal SignalProducer 17 — Reactive Programming Workshop, by Paul Taykalo,
#CocoaHeadsUkraine#13 -
Signal Producer vs Signal let tvSignal: Signal<EMChange,NoError> struct TV {
let signal: Signal<EMChange,NoError> let channels: [SignalProducer<Frame, Error>] } 18 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13 -
map Signal<V,E> -> Signal<V',E> 20 — Reactive Programming Workshop, by
Paul Taykalo, #CocoaHeadsUkraine#13 -
map let ints: Signal<Int, NoError> let strings = ints.map {
int in "\(int)"} // string: Signal<String, NoError> 21 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13 -
mapError Signal<V,E> -> Signal<V,E'> 22 — Reactive Programming Workshop, by
Paul Taykalo, #CocoaHeadsUkraine#13 -
mapError let ints: Signal<Int, NoError> let failableInts = ints.mapError {
err in CustomError.failed } // string: Signal<Int, CustomError> 23 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13 -
flatMap Signal<V,E> -> Signal<V',E'> 24 — Reactive Programming Workshop, by
Paul Taykalo, #CocoaHeadsUkraine#13 -
flatMap let strings: Signal<String, NoError> let ints = ints .flatMap(.latest)
{ string in guard let int = Int(string) else { return .init(error: CustomError.parsingFailed) } return .init(value: int) } // ints: Signal<Int, CustomError> 25 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13 -
flatMap let strings: Signal<String, NoError> let ints = ints .flatMap(.latest)
{ string in guard let int = Int(string) else { return .init(error: CustomError.parsingFailed) } return .init(value: int) } // ints: Signal<Int, CustomError> 26 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13 -
flatMap let strings: Signal<String, NoError> let ints = ints .flatMap(.latest)
{ string in guard let int = Int(string) else { return .init(error: CustomError.parsingFailed) } return .init(value: int) } // ints: Signal<Int, CustomError> 27 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13 -
flatMap let strings: Signal<String, NoError> let ints = ints .flatMap(.latest)
{ string in guard let int = Int(string) else { return .init(error: CustomError.parsingFailed) } return .init(value: int) } // ints: Signal<Int, CustomError> 28 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13 -
flatMap let getUserID: SignalProducer<User, NetworkError> let userIDs: SignalProducer<String, NoError> let
users = userIDs .producer .flatMap(.latest) { userID in getUserID(userID) } // users: SignalProducer<User, NetworkError> 29 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13 -
flatMap let userIDs: Signal<String, NoError> let getUserID: SignalProducer<User, NetworkError> let
users = userIDs .producer // Signal to SignalProducer .flatMap(.latest) { userID in getUserID(userID) } // users: SignalProducer<User, NetworkError> 30 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13 -
flatMap let userIDs: Signal<String, NoError> let getUserID: SignalProducer<User, NetworkError> let
users = userIDs .producer // Signal to SignalProducer .flatMap(.latest) { userID in getUserID(userID) } // users: SignalProducer<User, NetworkError> 31 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13 -
merge combineLatest zip collect 33 — Reactive Programming Workshop, by
Paul Taykalo, #CocoaHeadsUkraine#13 -
Let's go & Code 35 — Reactive Programming Workshop, by
Paul Taykalo, #CocoaHeadsUkraine#13 -
Workshop time Simple Signals & Merging 36 — Reactive Programming
Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13 -
Workshop time Values and Errors 37 — Reactive Programming Workshop,
by Paul Taykalo, #CocoaHeadsUkraine#13 -
Workshop time Chaining and Compiler 38 — Reactive Programming Workshop,
by Paul Taykalo, #CocoaHeadsUkraine#13 -
Reactive Rocks? 39 — Reactive Programming Workshop, by Paul Taykalo,
#CocoaHeadsUkraine#13 -
Railway oriented Programming 40 — Reactive Programming Workshop, by Paul
Taykalo, #CocoaHeadsUkraine#13 -
Railway oriented Programming 41 — Reactive Programming Workshop, by Paul
Taykalo, #CocoaHeadsUkraine#13 -
Errors Layering 43 — Reactive Programming Workshop, by Paul Taykalo,
#CocoaHeadsUkraine#13 -
Domain Objects 44 — Reactive Programming Workshop, by Paul Taykalo,
#CocoaHeadsUkraine#13 -
Domain Objects Domain Errors 45 — Reactive Programming Workshop, by
Paul Taykalo, #CocoaHeadsUkraine#13 -
class API { enum Error: Swift.Error { case unauthorized case
error(NSError) } func getUser() -> SignalProducer<JSON, Error> } 46 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13 -
class API { enum Error: Swift.Error { case unauthorized case
error(NSError) } func getUser() -> SignalProducer<JSON, Error> } 47 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13 -
class UserModel { enum Error: Swift.Error { case fetchFailed case
validationFailed } func getUser() -> SignalProducer<User, Error> { return api.getUser .mapError { e in .fetchFailed } .flatMap(.latest, validate) } } 48 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13 -
class UserModel { enum Error: Swift.Error { case fetchFailed case
validationFailed } func getUser() -> SignalProducer<User, Error> { return api.getUser .mapError { e in .fetchFailed } .flatMap(.latest, validate) } } 49 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13 -
class UserModel { enum Error: Swift.Error { case fetchFailed case
validationFailed } func getUser() -> SignalProducer<User, Error> { return api.getUser .mapError { e in .fetchFailed } .flatMap(.latest, validate) } } 50 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13 -
class UserModel { enum Error: Swift.Error { case fetchFailed case
validationFailed } func getUser() -> SignalProducer<User, Error> { return api.getUser .mapError { e in .fetchFailed } .flatMap(.latest, validate) } } 51 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13 -
Login -> Get User Info -> Get User Profile ->
Allow User to Login -> 53 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13 -
We need Reactive API! 55 — Reactive Programming Workshop, by
Paul Taykalo, #CocoaHeadsUkraine#13 -
public func reactive<Value>\( call: @escaping ( @escaping(Value) -> (), @escaping
(NSError) -> () ) -> () ) -> SignalProducer<Value, Error> { return SignalProducer.init { o, l in call( { o.send(value: $0); o.sendCompleted()}, { o.send(error: .error($0)) }) } } 56 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13 -
func getUser() -> SignalProducer<User, Error> { return reactive(call: Network.getUser) }
57 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13 -
Thank you 59 — Reactive Programming Workshop, by Paul Taykalo,
#CocoaHeadsUkraine#13 -
Reactive Programming Workshop by Paul Taykalo, Stanfy 60 — Reactive
Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13 -
The end 61 — Reactive Programming Workshop, by Paul Taykalo,
#CocoaHeadsUkraine#13 -
Links https://gist.github.com/JaviLorbada/ 4a7bd6129275ebefd5a6 https://fsharpforfunandprofit.com/rop/ 62 — Reactive Programming Workshop, by
Paul Taykalo, #CocoaHeadsUkraine#13 -
More links 63 — Reactive Programming Workshop, by Paul Taykalo,
#CocoaHeadsUkraine#13