Reactive cocoa cocoaheadsbe_2014

60 %
40 %
Information about Reactive cocoa cocoaheadsbe_2014
Technology

Published on March 13, 2014

Author: wernerramaekers

Source: slideshare.net

Description

Presentation on ReactiveCocoa given at the CocoaHeadsBE presentation on March 12th 2014.

ReactiveCocoa Werner Ramaekers Jan Sabbe Cocoaheads BE 12/03/2014

ReactiveCocoa (RAC) is an Objective-C framework for Functional Reactive Programming. It provides APIs for composing and transforming streams of values.

Whut ?

Programming PIN OUT Take inputs Produce outputs

Imperative programming •int x; int y = 1; int z = 2; •x = y + z; //x == 3; y == 1; z == 2; ! PIN OUT

Imperative programming •int x; int y = 1; int z = 2; •x = y + z; //x == 3; y == 1; z == 2; ! PIN OUT •y = 2; •NSLog(@“%i”, x); //-> ‘3’ ! # Input changed but output did NOT because it was declared earlier….

Imperative programming •int x; int y = 1; int z = 2; •x = y + z; //x == 3; y == 1; z == 2; ! PIN OUT STATE•y = 2; •NSLog(@“%i”, x); //-> ‘3’ ! # Input changed but output did NOT because it was declared earlier….

Declaractive programming •The developer describes the problem domain in a declarative way, ! •The focus is NOT on state ! •Focus is on : •data flow •propagation of change

Functional Programming •is one way of declarative programming. ! •Functional programming.. •deemphasizes state & mutable data •emphasizes functions that produce outputs based on inputs : z = f(x, y) PIN OUT

Reactive Programming •also is a way of declarative programming ! •Reactive Programming .. •dynamically links the program’s behaviour to its continuously updating data stream PIN OUT

Reactive Programming •also is a way of declarative programming ! •Reactive Programming .. •dynamically links the program’s behaviour to its continuously updating data stream PIN OUT •E.g. : a spreadsheet application where •cell A1 (= B1 + C1)

Functional Reactive Programming •.. combines the FUNCTIONAL and REACTIVE programming styles. ! •.. links functions that observe continuous and dynamic streams of data (inputs) to the program’s behaviour (outputs) in real time.

ReactiveCocoa (RAC) is an Objective-C framework for Functional Reactive Programming. It provides APIs for composing and transforming streams of values.

RAC : ReActiveCocoa Stream Subscriber RACStream produces a Stream existing of …

RAC : ReActiveCocoa Stream Next Event Subscriber RACStream produces a Stream existing of …

RAC : ReActiveCocoa Stream Next Event Complete Event Subscriber RACStream produces a Stream existing of …

RAC : ReActiveCocoa Stream Next Event Complete Event Subscriber Error Event RACStream produces a Stream existing of …

RAC : ReActiveCocoa Stream Subscriber [ 1, 2, 3] RACSequence

RAC : ReActiveCocoa Stream Subscriber [ 1, 2, 3] 123 RACSequence

RAC : ReActiveCocoa Stream Subscriber RACSignal Client Server

RAC : ReActiveCocoa Stream Subscriber… JSON RACSignal Client Server

RAC : ReActiveCocoa Stream Subscriber… ∞ RACSignal Client listen

RAC : ReActiveCocoa RACStream RACSignal RACSequence

ReactiveCocoa •RACStream •abstract class •represents some sequential flow of data •RACSignal (cold) •push-driven data stream of future values •cfr Network call •must be subscribed to in order to access data •RACSequence •pull-driven data stream •similar to Cocoa collection classes (NSArray, ..) •but values are evaluated lazily - only when needed

Details please

RACSignal ! [self.textField.rac_textSignal subscribeNext:^(id x) { NSLog(@“New value : %@“, x); } error:^(NSError *error){ NSLog(@“Error : %@“, error); } completed:^{ NSLog(@“That’s all folks !”); }];

RACSignal ! [self.textField.rac_textSignal subscribeNext:^(id x) { NSLog(@“New value : %@“, x); ! ! ! ! }];

RACSignal : combineLatest 123 C.L. ( )=,

RACStream operators •Simplifies transformations of streams into new streams •map, filter, fold/reduce !

RACStream : map MAP = ( ) = RACSequence *stream = [@[@(1), @(2), @(3)] rac_sequence]; [stream map:^id(id value) { return @(pow([value integerValue], 2)); }]; NSLog(@“%@“, [stream array]);

RACStream : flatten map FMAP = ( ) = Function result = stream

RACStream : filter RACSequence *stream = [@[@(1), @(2), @(3)]; rac_sequence]; NSLog(@“%@“, [[[array rac_sequence] filter:^BOOL(id value){ return [value integerValue] % 2 == 0; }] array] ); Filter = ( ) = True ?

Validating input the “old” way #pragma mark - UITextFieldDelegate ! - (BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { self.createButton.enabled = [self isFormValid]; ! return YES; }

Validating input the “old” way #pragma mark - UITextFieldDelegate ! - (BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { self.createButton.enabled = [self isFormValid]; ! return YES; } - (BOOL)isFormValid { return [self.usernameField.text length] > 0 && [self.emailField.text length] > 0 && [self.passwordField.text length] > 0 && [self.passwordField.text isEqual:self.passwordVerificationField.text]; } … …… …

Validating input the “RAC” way RAC(self.createButton, enabled) = ! [RACSignal combineLatest:@[ self.usernameTF.rac_textSignal, self.emailFieldTF.rac_textSignal, self.passwordFieldTF.rac_textSignal, self.passwordVerificationFieldTF.rac_textSignal ] reduce:^(NSString *username, NSString *email, NSString *password, NSString *passwordVerification) { return @([username length] > 0 && [email length] > 0 && [password length] > 8 && [password isEqual:passwordVerification]); }];

Validating input the “RAC” way RAC(self.createButton, enabled) = ! [RACSignal combineLatest:@[ self.usernameTF.rac_textSignal, self.emailFieldTF.rac_textSignal, self.passwordFieldTF.rac_textSignal, self.passwordVerificationFieldTF.rac_textSignal ] reduce:^(NSString *username, NSString *email, NSString *password, NSString *passwordVerification) { return @([username length] > 0 && [email length] > 0 && [password length] > 8 && [password isEqual:passwordVerification]); }];

“not so fast cowboy .. “ •RAC(object, key path) is a macro •creates a one-way binding •ex. bind “enabled” property of a UIButton to a signal

Now, show me a real app

Station locator app

Station locator app

Station locator app

Station locator app Core Data Stations GPS coord Services Prices

Station locator app Core Data Stations GPS coord Services Prices Driving distance

Station locator app Prices.xml Core Data Stations GPS coord Services Prices Driving distance

Station locator app Stations.xml Prices.xml Core Data Stations GPS coord Services Prices Driving distance

Easier asynchronous code Driving distance 1 2 3 Core Data lookup in Background current location

RAC( ) = (51.2, 5.46) station (id=4) flattenMap 
 searchClosest(51.2,5.46) flattenMap 
 getDrivingDistance(4) JSON map 
 JSON -> km "4.5 km"

Sort stations by driving distance station (id=1) station (id=3) station (id=2) getDrivingDistance combineLatest 
 sort [3,1,2] fetching driving distances concurrently when all available, sort

MVC

MVC

Scott, how do we test UIViewControllers

ViewModel pattern ViewController
 sets up binding
 animations ViewModel
 (BOOL) shop
 (BOOL) bread
 (RACCommand) search SearchService
 (RACSignal) searchWithCriteria validates + delegate to service do actual search

ViewModel pattern ViewController
 sets up binding
 animations ViewModel
 (BOOL) shop
 (BOOL) bread
 (RACCommand) search SearchService
 (RACSignal) searchWithCriteria mock out the real search service do search against in memory DB easily testable harder to test hard to test but trivial

ViewModel pattern ViewController
 sets up binding
 animations ViewModel
 (BOOL) shop
 (BOOL) bread
 (RACCommand) search SearchService
 (RACSignal) searchWithCriteria validates + delegate to service do actual search what is this?

RACCommand while getting current location, searching stations, sort by driving distance,... show activity indicator [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id sender) { return [self createSearchSignal]; }]; ViewModel

RACCommand while getting current location, searching stations, sort by driving distance,... show activity indicator [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id sender) { return [self createSearchSignal]; }]; ViewModel ViewController self.searchButton.rac_command = self.viewModel.searchCommand; RAC(self, spinner.hidden) = [self.viewModel.searchCommand.executing not];

ReactiveCocoa … •keeps the app focused on representing data & UX •can reduce complexity bc you don’t need to worry about ‘state’ so much •keeps related code close together (via blocks) •helps to make your code more testable (via MVVM)

but ReactiveCocoa … •introduces another way of thinking. •adds another learning curve on top of Cocoa ! •is a framework by GitHub and not Apple ! •will Apple "sherlock" ReactiveCocoa ?

One last thing

Thank you

#pragma presentations

Add a comment

Related presentations

Related pages

Reactive cocoa cocoaheadsbe_2014 - HubSlide

Presentation on ReactiveCocoa given at the CocoaHeadsBE presentation on March 12th 2014.
Read more

Reactive cocoa - Documents - docslide.us

3. What is ReactiveCocoa?•ReactiveCocoa = Functional Reactive(Binding) Programming 4. MVC ViewController exists many glue code. 5. Cocoa Binding(Mac ...
Read more