Slide 1

Slide 1 text

Reactive Programming Workshop by Paul Taykalo, Stanfy 1 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 2

Slide 2 text

Plan 2 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

About Reactive Programming 4 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 5

Slide 5 text

Async vs Sync 5 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 6

Slide 6 text

Everything is a Stream 6 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 7

Slide 7 text

Stream of values over time 7 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

Observable Signal SignalProduc 9 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 10

Slide 10 text

Signal 10 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 11

Slide 11 text

Signal 11 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 12

Slide 12 text

Signal 12 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 13

Slide 13 text

Signal 13 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 14

Slide 14 text

Signal Events enum Event { case value(Value) case failed(Error) case completed case interrupted } 14 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 15

Slide 15 text

Signal Termination enum Event { case value(Value) case failed(Error) // ❌ case completed // ❌ case interrupted // ❌ } 15 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 16

Slide 16 text

Signal SignalProducer 16 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 17

Slide 17 text

Signal SignalProducer 17 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 18

Slide 18 text

Signal Producer vs Signal let tvSignal: Signal struct TV { let signal: Signal let channels: [SignalProducer] } 18 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 19

Slide 19 text

Transformations 19 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 20

Slide 20 text

map Signal -> Signal 20 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 21

Slide 21 text

map let ints: Signal let strings = ints.map { int in "\(int)"} // string: Signal 21 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 22

Slide 22 text

mapError Signal -> Signal 22 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 23

Slide 23 text

mapError let ints: Signal let failableInts = ints.mapError { err in CustomError.failed } // string: Signal 23 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 24

Slide 24 text

flatMap Signal -> Signal 24 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 25

Slide 25 text

flatMap let strings: Signal let ints = ints .flatMap(.latest) { string in guard let int = Int(string) else { return .init(error: CustomError.parsingFailed) } return .init(value: int) } // ints: Signal 25 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 26

Slide 26 text

flatMap let strings: Signal let ints = ints .flatMap(.latest) { string in guard let int = Int(string) else { return .init(error: CustomError.parsingFailed) } return .init(value: int) } // ints: Signal 26 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 27

Slide 27 text

flatMap let strings: Signal let ints = ints .flatMap(.latest) { string in guard let int = Int(string) else { return .init(error: CustomError.parsingFailed) } return .init(value: int) } // ints: Signal 27 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 28

Slide 28 text

flatMap let strings: Signal let ints = ints .flatMap(.latest) { string in guard let int = Int(string) else { return .init(error: CustomError.parsingFailed) } return .init(value: int) } // ints: Signal 28 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 29

Slide 29 text

flatMap let getUserID: SignalProducer let userIDs: SignalProducer let users = userIDs .producer .flatMap(.latest) { userID in getUserID(userID) } // users: SignalProducer 29 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 30

Slide 30 text

flatMap let userIDs: Signal let getUserID: SignalProducer let users = userIDs .producer // Signal to SignalProducer .flatMap(.latest) { userID in getUserID(userID) } // users: SignalProducer 30 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 31

Slide 31 text

flatMap let userIDs: Signal let getUserID: SignalProducer let users = userIDs .producer // Signal to SignalProducer .flatMap(.latest) { userID in getUserID(userID) } // users: SignalProducer 31 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 32

Slide 32 text

Combinations 32 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 33

Slide 33 text

merge combineLatest zip collect 33 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 34

Slide 34 text

Other 34 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 35

Slide 35 text

Let's go & Code 35 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 36

Slide 36 text

Workshop time Simple Signals & Merging 36 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 37

Slide 37 text

Workshop time Values and Errors 37 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 38

Slide 38 text

Workshop time Chaining and Compiler 38 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 39

Slide 39 text

Reactive Rocks? 39 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 40

Slide 40 text

Railway oriented Programming 40 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 41

Slide 41 text

Railway oriented Programming 41 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 42

Slide 42 text

SideEffects 42 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 43

Slide 43 text

Errors Layering 43 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 44

Slide 44 text

Domain Objects 44 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 45

Slide 45 text

Domain Objects Domain Errors 45 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 46

Slide 46 text

class API { enum Error: Swift.Error { case unauthorized case error(NSError) } func getUser() -> SignalProducer } 46 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 47

Slide 47 text

class API { enum Error: Swift.Error { case unauthorized case error(NSError) } func getUser() -> SignalProducer } 47 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 48

Slide 48 text

class UserModel { enum Error: Swift.Error { case fetchFailed case validationFailed } func getUser() -> SignalProducer { return api.getUser .mapError { e in .fetchFailed } .flatMap(.latest, validate) } } 48 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 49

Slide 49 text

class UserModel { enum Error: Swift.Error { case fetchFailed case validationFailed } func getUser() -> SignalProducer { return api.getUser .mapError { e in .fetchFailed } .flatMap(.latest, validate) } } 49 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 50

Slide 50 text

class UserModel { enum Error: Swift.Error { case fetchFailed case validationFailed } func getUser() -> SignalProducer { return api.getUser .mapError { e in .fetchFailed } .flatMap(.latest, validate) } } 50 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 51

Slide 51 text

class UserModel { enum Error: Swift.Error { case fetchFailed case validationFailed } func getUser() -> SignalProducer { return api.getUser .mapError { e in .fetchFailed } .flatMap(.latest, validate) } } 51 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 52

Slide 52 text

Example 52 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 53

Slide 53 text

Login -> Get User Info -> Get User Profile -> Allow User to Login -> 53 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 54

Slide 54 text

Flow 54 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 55

Slide 55 text

We need Reactive API! 55 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 56

Slide 56 text

public func reactive\( call: @escaping ( @escaping(Value) -> (), @escaping (NSError) -> () ) -> () ) -> SignalProducer { 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

Slide 57

Slide 57 text

func getUser() -> SignalProducer { return reactive(call: Network.getUser) } 57 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 58

Slide 58 text

58 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 59

Slide 59 text

Thank you 59 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 60

Slide 60 text

Reactive Programming Workshop by Paul Taykalo, Stanfy 60 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 61

Slide 61 text

The end 61 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 62

Slide 62 text

Links https://gist.github.com/JaviLorbada/ 4a7bd6129275ebefd5a6 https://fsharpforfunandprofit.com/rop/ 62 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13

Slide 63

Slide 63 text

More links 63 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13