Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Reactive Programming Workshop

Reactive Programming Workshop

Slides for Reactive Programming workshop. Reactive Swift. Signals, Signal Producers etc

Paul Taykalo

February 25, 2018
Tweet

More Decks by Paul Taykalo

Other Decks in Programming

Transcript

  1. Reactive Programming Workshop by Paul Taykalo, Stanfy 1 — Reactive

    Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13
  2. 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
  3. 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
  4. 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
  5. 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
  6. 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
  7. 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
  8. 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
  9. 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
  10. 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
  11. 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
  12. 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
  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
  14. 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
  15. 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
  16. Let's go & Code 35 — Reactive Programming Workshop, by

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

    Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13
  18. 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
  19. 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
  20. 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
  21. 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
  22. 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
  23. 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
  24. Login -> Get User Info -> Get User Profile ->

    Allow User to Login -> 53 — Reactive Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13
  25. 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
  26. func getUser() -> SignalProducer<User, Error> { return reactive(call: Network.getUser) }

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

    Programming Workshop, by Paul Taykalo, #CocoaHeadsUkraine#13