Reactive cocoa

16
Reactive Cocoa “A framework for composing and transforming streams of values.”

Transcript of Reactive cocoa

Page 1: Reactive cocoa

Reactive Cocoa“A framework for composing and transforming streams of values.”

Page 2: Reactive cocoa

Reactive Cocoa

Reactive Cocoa is a third-party Objective C framework which has received some interested and a community-following.

Page 3: Reactive cocoa

Functional Programming

Functional programming is a style of programming based on a formal model of computation called lambda calculus.

Some programming languages such as Lisp (and its children Scheme and Clojure), Haskell, Scala, ML called functional programming languages because they are very amenable to this style of programming, although it can technically be done with many other languages.

Languages like C, Objective C, and Java are called imperative because programs are often written in a different style and these languages support that style.

For our purposes, functional programming means programs are composed of functions.

f(x) = x+5, g(x) = x+2

We can evaluate functions which are composed together by substitution.

f(g(4))f(4+2)f(6)6+511

Given an input, we always get the same output.

Page 4: Reactive cocoa

Functional programming tend to operate on lists, which are seen as a sequences of values.

list = (1, 2, 3)

Calling it a sequence is important. Generally, lists are treated as the first element (head) and the rest of the elements besides the head.

list.head = 1, list.tail = (2, 3)

This is different from an array where any element can be accessed at one time.

list[2]

This approach has the advantage of allowing some programs to be written in a recursive style.

int maxValue(currentMax, list) {if (list.empty) return currentMaxelse if (list.head > currentMax) return maxValue(list.head, list.tail)else maxValue(currentMax, list.tail)

}

Also: infinite streams.

Page 5: Reactive cocoa

The ability to have that kind of mutable state is forbidden in pure functional programming. In practice, pure functional programming does not have assignment.

(Maybe languages that support functional programming do, in fact, allow assignment.)

It turns out, this is an excellent feature for designing applications that work with concurrency. This is one reason why functional programming has received a lot of interest recently (and why, for example, Apple brought blocks to C / Objective C in 2009).

Page 6: Reactive cocoa

But following this rule presents a challenge for working with user input.

Imagine you wanted to write a function which gets keystrokes one character at a time.

char getCharacter();

This function is not really compatible with functional styles of programming, because it might return any character from the same input (in this case, nothing).

Page 7: Reactive cocoa

- (int)maxOfX:(int)x Y:(int)y { if (x > y)

return x; else

return y;}

//////

@property (nonatomic) int x;

- (void)buttonPressed:(id)sender {if (self.x == 0)

self.x = 100;else

self.x = 0;}

- (int)maxOfXandY:(int)y {if (self.x > y)

return self.x;else

return y;}

[self maxOfX:50 andY:75];

//////

[self maxOfXandY:75];

Page 8: Reactive cocoa

Functional Reactive Programming

There are a lot of various implementations of Functional Reactive Programming (e.g. Elm).

It handles the problems of dealing with user input by treating it as the parameters of functions, executing them again and again as the input changes.

function ( ) {

}

Page 9: Reactive cocoa

Reactive Cocoa

Based on Microsoft’s Rx Extensions.

Developed by engineers at GitHub.

It is quite large. It may be best to consider it an extension to the Objective C language.

My plan is only to demonstrate some practical examples, focusing on the concept of signals.

Page 10: Reactive cocoa

Signals

[RACObserve(self, firstName) subscribeNext:^(NSString *newName) { NSLog(@"%@", newName); }]; self.firstName = @"Matt"; [[RACObserve(self, lastName) filter:^(NSString *newName) { return [newName hasPrefix:@"Gill"]; }] subscribeNext:^(NSString *newName) { NSLog(@"%@", newName); }]; self.lastName = @"Jones"; self.lastName = @"Gillingham"; self.lastName = @"Mayberry";

Page 11: Reactive cocoa

Combine Signals RACSignal *signal1 = @[@(1)].rac_sequence.signal; RACSignal *signal2 = @[@(2)].rac_sequence.signal; [[RACSignal merge:@[signal1, signal2]] subscribeCompleted:^{ NSLog(@"They're both done!"); }]; [signal1 subscribeNext:^(id x) { NSLog(@"Signal 1: %@", x); }];

[signal2 subscribeNext:^(id x) { NSLog(@"Signal 2: %@", x); }];

Page 12: Reactive cocoa

UI as Signals

self.textField = [[UITextField alloc] initWithFrame: CGRectMake(10.0f, 10.0f, 100.0f, 44.0f) ]; [self.textField.rac_textSignal subscribeNext:^(id x) { NSLog(@“1: %@", x); }]; [self.textField.rac_textSignal subscribeNext:^(id x) { NSLog(@“2: %@", x); }]; [self.view addSubview:self.textField];

Page 13: Reactive cocoa

A More Complex Example

self.email1Field = [[UITextField alloc] initWithFrame:CGRectMake(30.0f, 130.0f, 200.0f, 30.0f)]; self.email1Field.borderStyle = UITextBorderStyleLine; [self.view addSubview:self.email1Field]; self.email2Field = [[UITextField alloc] initWithFrame:CGRectMake(30.0f, 165.0f, 200.0f, 30.0f)]; self.email2Field.borderStyle = UITextBorderStyleLine; [self.view addSubview:self.email2Field]; self.submitButton = [UIButton buttonWithType:UIButtonTypeSystem]; [self.submitButton setTitle:@"Submit" forState:UIControlStateNormal]; self.submitButton.frame = CGRectMake(30.0f, 200.0f, 200.0f, 30.0f); self.submitButton.enabled = NO; [[[[RACSignal merge:@[self.email1Field.rac_textSignal, self.email2Field.rac_textSignal]] map:^id(id value) { return @([self.email1Field.text isEqualToString:self.email2Field.text]); }] distinctUntilChanged] subscribeNext:^(NSNumber *equal) { self.submitButton.enabled = [equal boolValue]; }]; [self.view addSubview:self.email1Field]; [self.view addSubview:self.email2Field]; [self.view addSubview:self.submitButton];

Page 14: Reactive cocoa

Note on Concurrency

No two subscription blocks can be called simultaneously to avoid deadlock.

You can control which thread the subscription block is called on with RACScheduler

This allows for signals to mimic an NSOperationQueue.

Page 15: Reactive cocoa

Conclusion

ReactiveCocoa is based on some relatively abstract concepts but these concepts turn out to be very, very powerful in practice.

Signals, for example, may be able to replace KVO, operation queues and delegation in an app. I have barely touched the available feature set in these examples.

Page 16: Reactive cocoa

Conclusion

It does require a lot of abstract thinking to determine how to model your apps behavior as a series of signals.

For this reason, there is a learning curve associated with it.

Personally, I am very likely use it in the future.