ReactiveCocoa functional reactive programming in iOS Andrei Popa
A. current challenges in programming - keeping state, inputs, asynchronous tasks, callback hell B. how does Functional Reactive Programming solve them - the functional aspect - the reactive aspect C. ReactiveCocoa - mature FRP implementation for iOS D. Examples
- the input is all the sources of action for your app: button taps, keyboard events, timer triggers, GPS events, web service responses, etc. - the output at any one time is the result of combining all inputs. - ft (input) = output - but unlike the classic input / output design, this input and output happens more than once. It’s not just a single input - work - output, the cycle continues while the app is open first problem: state
first problem: state And so our only tool for dealing with all these different things is state.
• obviously this is highly error prone • to make matters worse, this type of code will often produce bugs that are incredibly hard, if not impossible to identify in any automated way • state introduces complexity. And worse, it introduces complexity that grows more than linearly with the size of our app first problem: state
nondeterministic vs deterministic
nondeterministic vs deterministic - most developers have experienced the problems of non- determinism when a client calls in with a problem, but the problem is not reproducible even by retracing the exact same steps - if the program was deterministic, then retracing those exact steps would always produce the error, no exception - for testing and quality assurance purposes, reproducibility is essential
types of inputs - iOS
asynchronous operations - network requests - resource loading - image processing - bluetooth operations - file I/O What happens when several different asynchronous operations must be executed in some set order (serialized)?
asynchronous operations callback hell aka Pyramid of Doom
asynchronous operations callback hell aka Pyramid of Doom
functional programming = stateless programming - fundamental operation is the application of functions to arguments. - passing functions and blocks as objects - there is no mutable state in functional programming - f (input) = output , always produces the same output given the same input. Always. - it doesn’t rely / change on data outside the current function
functional programming = stateless programming
If we had machines that had infinite computational power, what problems would we be able to solve? - Alonzo Church developed λ - lambda calculus Computability described via λ-calculus gave rise to Functional Programming - Alan Turing developed Turing machine Computability via Turing machines gave rise to Imperative Programming. Church-Turing thesis: The notion of intuitive computability is exactly captured by λ-definability or by Turing computability.
who is using functional programming ? Some of the most complex systems written using Erlang: - telecommunication and traffic control systems - Ericsson (highly tolerant and scalable telecommunication switches) - Facebook (Facebook chat backend) - T-Mobile (advanced call control services) - WhatsApp server - average of 8 billion inbound messages and 12 billion outbound messages a day - WhatsApp scales up to more than a million connections on a single box thanks to Erlang’s amazing scalability
reactive programming In computing, reactive programming is a programming paradigm oriented around data flows and the propagation of change. We don’t care how it happens – just that we can rely on its truthfulness.
functional reactive programming time-varying values - lets us define our app in terms of the time-varying values and ensures changes propagate as needed. - the result of asynchronous work is really just a time-varying value that only has a value once the work is done - a UI element’s value could be seen as a time-varying value that changes as the user interacts with it - if my app is running on a mobile device, the device’s GPS coordinates is a time-varying value
1. model any reaction to any event using signals - wrap calls in RACSignal (ObjC) / SignalProducer (Swift) 2. manipulate, transform, combine values sent by signals - map, filter, flattenMap, zip, concat, merge, … - throttle, delay, repeat, then, take, distinctUntilChanged, … - deliverOn(someThread), subscribeOn(someOtherThread) - subscribe ReactiveCocoa provides a common interface for all events : signal
ReactiveCocoa unifies all of Cocoa’s common patterns for asynchrony and event handling
ReactiveCocoa unifies all of Cocoa’s common patterns for asynchrony and event handling
Examples
1) Take pictures burst mode 2) Apply filter 3) Put frame 4) Send to back for generating animated GIF
- (RACSignal *) generateCats { return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { // my long async call ——————————————————————————- [[MyCameraManager sharedInstance] takePicturesBurstMode:^(UIImage *image, NSError *error) { if (error) { [subscriber sendError:error]; } else { [subscriber sendNext:image]; [subscriber sendCompleted]; } }]; // —————————————————————————————————————————————— return nil; }]; } 1) take pictures
- (UIImage *) applyFilter(UIImage *) { return ; } [[signalFactory generateCats] map:^id(UIImage *cat) { return applyFilter(cat); }]; 2) apply filter
- (UIImage *) putFrame(UIImage *)image { return image ; } [[[signalFactory generateCats] map:^id(UIImage *cat) { return applyFilter(cat); }] map:^id(UIImage *cat) { return putFrame(cat); }]; 3) put frame
[[[[[signalFactory generateCats] map:^id(UIImage *cat) { return applyFilter(cat); }] map:^id(UIImage *cat) { return putFrame(cat); }] collect] // combine all next events into one NSArray flattenMap:^RACStream *(NSArray *allCats) { // [signalFactory sendAsyncToBackend:allCats] is a RACSignal return [signalFactory sendAsyncToBackend:allCats]; }]; // this will still be a RACSignal 4) Send to back for generating animated GIF
[[[[[[signalFactory generateCats] // take pictures map:^id(UIImage *cat) { return applyFilter(cat); }] // apply filter map:^id(UIImage *cat) { return putFrame(cat); }]] // put frame collect] // get all the processed images flattenMap:^RACStream *(NSArray *allCats) { return [signalFactory sendAsyncToBackend:allCats]; }] // send async call and wait for the result // signal is started when someone subscribes subscribeNext:^(UIImage *animatedGIF) { // success!, display GIF } error:^(NSError *error) { // error }]; 5) see the result
ReactiveCocoa Bindings in MVVM architecture using RAC Signals
- http://rxmarbles.com/ - http://www.sprynthesis.com/2014/06/15/why-reactivecocoa/ - http://www.sprynthesis.com/2014/12/06/reactivecocoa-mvvm- introduction/ - http://www.raywenderlich.com/62699/reactivecocoa-tutorial-pt1 - https://developers.soundcloud.com/blog/building-the-new-ios-app-a- new-paradigm - https://github.com/popaaaandrei/StarterProject_RACSwift2 The end. Thank you! Q&A

ReactiveCocoa - Functional Reactive Programming concepts in iOS

  • 1.
  • 2.
    A. current challengesin programming - keeping state, inputs, asynchronous tasks, callback hell B. how does Functional Reactive Programming solve them - the functional aspect - the reactive aspect C. ReactiveCocoa - mature FRP implementation for iOS D. Examples
  • 3.
    - the inputis all the sources of action for your app: button taps, keyboard events, timer triggers, GPS events, web service responses, etc. - the output at any one time is the result of combining all inputs. - ft (input) = output - but unlike the classic input / output design, this input and output happens more than once. It’s not just a single input - work - output, the cycle continues while the app is open first problem: state
  • 4.
    first problem: state Andso our only tool for dealing with all these different things is state.
  • 6.
    • obviously thisis highly error prone • to make matters worse, this type of code will often produce bugs that are incredibly hard, if not impossible to identify in any automated way • state introduces complexity. And worse, it introduces complexity that grows more than linearly with the size of our app first problem: state
  • 7.
  • 8.
    nondeterministic vs deterministic -most developers have experienced the problems of non- determinism when a client calls in with a problem, but the problem is not reproducible even by retracing the exact same steps - if the program was deterministic, then retracing those exact steps would always produce the error, no exception - for testing and quality assurance purposes, reproducibility is essential
  • 9.
  • 10.
    asynchronous operations - networkrequests - resource loading - image processing - bluetooth operations - file I/O What happens when several different asynchronous operations must be executed in some set order (serialized)?
  • 11.
  • 12.
  • 13.
    functional programming =stateless programming - fundamental operation is the application of functions to arguments. - passing functions and blocks as objects - there is no mutable state in functional programming - f (input) = output , always produces the same output given the same input. Always. - it doesn’t rely / change on data outside the current function
  • 14.
    functional programming =stateless programming
  • 15.
    If we hadmachines that had infinite computational power, what problems would we be able to solve? - Alonzo Church developed λ - lambda calculus Computability described via λ-calculus gave rise to Functional Programming - Alan Turing developed Turing machine Computability via Turing machines gave rise to Imperative Programming. Church-Turing thesis: The notion of intuitive computability is exactly captured by λ-definability or by Turing computability.
  • 16.
    who is usingfunctional programming ? Some of the most complex systems written using Erlang: - telecommunication and traffic control systems - Ericsson (highly tolerant and scalable telecommunication switches) - Facebook (Facebook chat backend) - T-Mobile (advanced call control services) - WhatsApp server - average of 8 billion inbound messages and 12 billion outbound messages a day - WhatsApp scales up to more than a million connections on a single box thanks to Erlang’s amazing scalability
  • 17.
    reactive programming In computing,reactive programming is a programming paradigm oriented around data flows and the propagation of change. We don’t care how it happens – just that we can rely on its truthfulness.
  • 18.
    functional reactive programming time-varyingvalues - lets us define our app in terms of the time-varying values and ensures changes propagate as needed. - the result of asynchronous work is really just a time-varying value that only has a value once the work is done - a UI element’s value could be seen as a time-varying value that changes as the user interacts with it - if my app is running on a mobile device, the device’s GPS coordinates is a time-varying value
  • 19.
    1. model anyreaction to any event using signals - wrap calls in RACSignal (ObjC) / SignalProducer (Swift) 2. manipulate, transform, combine values sent by signals - map, filter, flattenMap, zip, concat, merge, … - throttle, delay, repeat, then, take, distinctUntilChanged, … - deliverOn(someThread), subscribeOn(someOtherThread) - subscribe ReactiveCocoa provides a common interface for all events : signal
  • 20.
    ReactiveCocoa unifies all ofCocoa’s common patterns for asynchrony and event handling
  • 21.
    ReactiveCocoa unifies all ofCocoa’s common patterns for asynchrony and event handling
  • 23.
  • 24.
    1) Take pictures burstmode 2) Apply filter 3) Put frame 4) Send to back for generating animated GIF
  • 25.
    - (RACSignal *)generateCats { return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { // my long async call ——————————————————————————- [[MyCameraManager sharedInstance] takePicturesBurstMode:^(UIImage *image, NSError *error) { if (error) { [subscriber sendError:error]; } else { [subscriber sendNext:image]; [subscriber sendCompleted]; } }]; // —————————————————————————————————————————————— return nil; }]; } 1) take pictures
  • 26.
    - (UIImage *)applyFilter(UIImage *) { return ; } [[signalFactory generateCats] map:^id(UIImage *cat) { return applyFilter(cat); }]; 2) apply filter
  • 27.
    - (UIImage *)putFrame(UIImage *)image { return image ; } [[[signalFactory generateCats] map:^id(UIImage *cat) { return applyFilter(cat); }] map:^id(UIImage *cat) { return putFrame(cat); }]; 3) put frame
  • 28.
    [[[[[signalFactory generateCats] map:^id(UIImage *cat){ return applyFilter(cat); }] map:^id(UIImage *cat) { return putFrame(cat); }] collect] // combine all next events into one NSArray flattenMap:^RACStream *(NSArray *allCats) { // [signalFactory sendAsyncToBackend:allCats] is a RACSignal return [signalFactory sendAsyncToBackend:allCats]; }]; // this will still be a RACSignal 4) Send to back for generating animated GIF
  • 29.
    [[[[[[signalFactory generateCats] //take pictures map:^id(UIImage *cat) { return applyFilter(cat); }] // apply filter map:^id(UIImage *cat) { return putFrame(cat); }]] // put frame collect] // get all the processed images flattenMap:^RACStream *(NSArray *allCats) { return [signalFactory sendAsyncToBackend:allCats]; }] // send async call and wait for the result // signal is started when someone subscribes subscribeNext:^(UIImage *animatedGIF) { // success!, display GIF } error:^(NSError *error) { // error }]; 5) see the result
  • 33.
    ReactiveCocoa Bindings in MVVMarchitecture using RAC Signals
  • 34.
    - http://rxmarbles.com/ - http://www.sprynthesis.com/2014/06/15/why-reactivecocoa/ -http://www.sprynthesis.com/2014/12/06/reactivecocoa-mvvm- introduction/ - http://www.raywenderlich.com/62699/reactivecocoa-tutorial-pt1 - https://developers.soundcloud.com/blog/building-the-new-ios-app-a- new-paradigm - https://github.com/popaaaandrei/StarterProject_RACSwift2 The end. Thank you! Q&A