Slide 1

Slide 1 text

ReactiveCocoa Ash Furrow

Slide 2

Slide 2 text

— Shunryu Suzuki “In the beginner’s mind there are many possibilities, in the expert's mind there are few.”

Slide 3

Slide 3 text

Agenda • Imperative programming is antiquated and dangerous • Functional reactive programming mitigates those dangers • ReactiveCocoa makes FRP easy

Slide 4

Slide 4 text

BNE ADD1 BRA NONE1 ADD1 INY ;increment our counter of 1's NONE1 LDAA TEMP ;reload accumulator A LSL MASK ;Shift the mask's 1 bit left BNE LOOP1 ;If we haven't finished our loop, branch LDAA #$01 ;load new mask into A STAA MASK ;store the reset mask into MASK TSX ;pull of return address and store in X PULA ;pull off A STAA TEMP ;store the value into temp TXS ;push return address back onto the stack LOOP2 LDAA TEMP ;Load A into TEMP ANDA MASK ;logical AND MASK with A BNE ADD2 ;add one if we need to BRA NONE2 ADD2 INY ;increment our counter of 1's NONE2 LDAA TEMP LSL MASK ;shift our mask left by one BNE LOOP2 ;loop back until we've exhausted positions

Slide 5

Slide 5 text

Functional Reactive Programming

Slide 6

Slide 6 text

• Functional • Typically, functions have no side-effects • Programs are written as a series of data transformations

Slide 7

Slide 7 text

Demo https://github.com/AshFurrow/FunctionalDemo

Slide 8

Slide 8 text

• Reactive • When one thing changes, it effects changes in other things • Like a spreadsheet

Slide 9

Slide 9 text

Functional programming has limits. ! Reactive programming is limited by itself. ! FRP is peanut butter and chocolate of programming paradigms.

Slide 10

Slide 10 text

Functional Reactive Programming • In functional programming, things get hard because functions can’t have side-effects • (Every time a function is called, it must return the same result for the same parameters) • In functional reactive programming, time is an implicit parameter • This makes things easy to manage, without using monads

Slide 11

Slide 11 text

Signals • At the core of FRP are signals • Signals send values over time, until they complete or error out • A signal never sends anything after completing or erring • A signal either completes, or errors out, but never both • A signal has no concept of a “current value” or “past values” • It’s like a pipe

Slide 12

Slide 12 text

Signals • Signals can be chained to transform the values that the send • This is core to FRP: data transformation of values sent over time • In math terms, it’s f(g(y))

Slide 13

Slide 13 text

• ReactiveCocoa is a framework developed by GitHub • ReactiveCocoa is an implementation of FRP on iOS/OS X • It’s currently being revamped to version 3.0

Slide 14

Slide 14 text

Signals • Signals are built on KVO • Creating a signal is easy • RACObserve macro • Wraps a @property • Sends a new value for updated property values

Slide 15

Slide 15 text

RACSignal *signal = RACObserve(object, number); [signal subscribeNext:^id(NSNumber *value) { NSLog(@”%@”, value); }];

Slide 16

Slide 16 text

Signals • Signals always send id, never primitives • Will wrap primitives in NSNumber for you

Slide 17

Slide 17 text

Map • Mapping performs a value transformation on the given signal • It “maps” each value sent along the signal to a new value • It then passes that new value along, creating a new signal • This is the canonical value transformation

Slide 18

Slide 18 text

RACObserve map: subscribeNext:

Slide 19

Slide 19 text

RACSignal *signal = RACObserve(object, number); [[signal map:^id(NSNumber *value) { return [value stringValue]; }] subscribeNext:^id(NSString *string) { NSLog(@”%@”, string); }];

Slide 20

Slide 20 text

Combine Latest • Combines two or more signals’ values into one • Useful for waiting for conditions to be met • Useful for deciding between values

Slide 21

Slide 21 text

RACObserve combineLatest: reduce: RACObserve

Slide 22

Slide 22 text

[RACSignal combineLatest:@[someNumberSignal, someStringSignal] reduce:^id(NSNumber *number, NSString *string){ return [NSString stringWithFormat:@"%@:%@", number.stringValue, string]; }];

Slide 23

Slide 23 text

Filter • Filtering allows values that pass some test to “pass through”

Slide 24

Slide 24 text

RACObserve filter: subscribeNext:

Slide 25

Slide 25 text

[[someNumberSignal filter:^BOOL(NSNumber *value){ return value.integerValue > 5; }] map:^id(NSNumber *value) { return [value stringValue]; }];

Slide 26

Slide 26 text

Bindings • Bindings can bind a property to the latest value sent on a signal • Bindings are typically created with the RAC macro • All bindings created with the RAC macro are one-way • Bindings are the secret sauce that hold apps together

Slide 27

Slide 27 text

RAC(self.textField, text) = RACObserve(self, someString);

Slide 28

Slide 28 text

NSArray *signalArray = @[self.firstNameField.rac_textSignal, self.lastNameField.rac_textSignal]; ! RAC(self.button, enabled) = [RACSignal combineLatest:signalArray reduce:^(NSString *firstName, NSString *lastName){ return @(firstName.length > 0 && lastName.length > 0); }];

Slide 29

Slide 29 text

Derived State • State is avoided in ReactiveCocoa, but is unavoidable in Cocoa • Instead of hacky workarounds, we derive the state from signals • Similar to the last example’s enabled state binding

Slide 30

Slide 30 text

Other Operators • takeUntil: • scheduleOn: • throttle: • not, and, or

Slide 31

Slide 31 text

Commands • A command represents a unit of work • Typically, work that’s done in response to user action • Commands are … confusing • They’ve been replaced in ReactiveCocoa 3.0 by Actions

Slide 32

Slide 32 text

Two-Way Bindings • Two-way bindings exist, but their use is more rare under MVC • They’re more frequently used with MVVM • Created with RACChannelTo macro

Slide 33

Slide 33 text

Demo https://github.com/AshFurrow/FunctionalReactiveDemo

Slide 34

Slide 34 text

Demo • Notice subscribeNext: is used for side-effects • Cocoa Touch isn’t built on FRP, so we need side-effects • RACObserve captures self in its scope implicitly • Avoid reference cycles! • Network results are delivered on a background scheduler • Use deliverOn: to reschedule them

Slide 35

Slide 35 text

Model-View-ViewModel

Slide 36

Slide 36 text

View View Controller Model View Model owns owns Updates Updates

Slide 37

Slide 37 text

Getting Started • Getting started with ReactiveCocoa is easy • Install ReactiveCocoa in your project (CocoaPods or submodule) • Start by replacing KVO methods with RACObserve • Use subscribeNext: for side-effects

Slide 38

Slide 38 text

http://leanpub.com/iosfrp

Slide 39

Slide 39 text

@ashfurrow http://ashfurrow.com