Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
What the FRP? – Using Reactive Cocoa
Search
Jay Baird
July 23, 2013
Programming
3
250
What the FRP? – Using Reactive Cocoa
A talk I gave on using Reactive Cocoa in the Rackspace Cloud Control application at NSMeetup July.
Jay Baird
July 23, 2013
Tweet
Share
Other Decks in Programming
See All in Programming
Ruby on cygwin 2025-02
fd0
0
150
定理証明プラットフォーム lapisla.net
abap34
1
1.8k
苦しいTiDBへの移行を乗り越えて快適な運用を目指す
leveragestech
0
650
Rubyで始める関数型ドメインモデリング
shogo_tksk
0
120
Java Webフレームワークの現状 / java web framework at burikaigi
kishida
9
2.2k
XStateを用いた堅牢なReact Components設計~複雑なClient Stateをシンプルに~ @React Tokyo ミートアップ #2
kfurusho
1
920
SpringBoot3.4の構造化ログ #kanjava
irof
2
1k
メンテが命: PHPフレームワークのコンテナ化とアップグレード戦略
shunta27
0
130
Formの複雑さに立ち向かう
bmthd
1
860
Rails アプリ地図考 Flush Cut
makicamel
1
120
2024年のWebフロントエンドのふりかえりと2025年
sakito
3
250
How mixi2 Uses TiDB for SNS Scalability and Performance
kanmo
38
14k
Featured
See All Featured
VelocityConf: Rendering Performance Case Studies
addyosmani
328
24k
YesSQL, Process and Tooling at Scale
rocio
172
14k
Docker and Python
trallard
44
3.3k
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
44
7k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
120k
Unsuck your backbone
ammeep
669
57k
KATA
mclloyd
29
14k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
129
19k
Building Flexible Design Systems
yeseniaperezcruz
328
38k
Building a Scalable Design System with Sketch
lauravandoore
461
33k
Scaling GitHub
holman
459
140k
Transcript
What the FRP? Using Reactive Cocoa • NSMeetup July
Jay Baird • @skatterbean Work at Rackspace Indie iOS developer
None
Not an expert, just an enthusiast.
None
The dreaded server list view.
Regions Servers Images Sizes
None
make dependencies explicit
values can change over time
We wait for I/O. We wait for the disk. We
wait for users.
Data Flow
None
a graph of signals that propagate change Reactive Programming!
Reactive Cocoa a github joint • https://github.com/ReactiveCocoa
None
None
The Players
RACStream •Any series of object values available immediately or in
the future. •Monads and strife.
<RACSubscriber> • Protocol any object can adopt to receive values
from a signal. • Use RACSignal’s - subscribeNext:error:completed: convenience methods
RACSignal • Push driven stream • As work is completed
values are sent on the signal to its subscribers • Sends next, error and completed events • Can sends any number of next events, followed by one error or completed (but not both)
Example
Binding
RAC(self.image) = [[[client getImage:self.imageId] catch:^RACSignal *(NSError *error) { return [RACSignal
empty]; // swallow the error }] map:^(NSDictionary *imageDict) { return [Image fromJSON:imageDict[@"image"]]; }];
RACSubject • Think of it as RACMutableSignal • provides sendNext:,
sendError: and sendCompleted methods • Crazy useful for bridging other code, e.g. AFNetworking
Example
Timers
RACSubject *pollTimer = [RACSubject subject]; [[[RACSignal interval:60.0f] takeUntil:[pollTimer doNext:^(id x)
{ NSLog(@"Server poll cancelled"); }]] subscribeNext:^(id x) { NSLog(@"Tick."); } error:^(NSError *error) { NSLog(@"Handle the error condition"); } completed:^{ NSLog(@"Timer completed"); }]; // Cancels the timer. // A unit represents an empty value [pollTimer sendNext:[RACUnit defaultUnit]];
The dreaded server list view
RACSubject *subject = [RACSubject subject]; // +flavors returns a RACSignal
with flavors // +images returns a RACSignal with images [[RACSignal combineLatest:@[[Flavor flavors], [Image images]]] subscribeError:^(NSError *error) { [subject sendError:error]; } completed:^{ [[client getServers] subscribeNext:^(NSArray *serverJSON) { // Process server JSON [subject sendCompleted]; } error:^(NSError *error) { [subject sendError:error]; } completed:^{ [subject sendCompleted]; }]; }]; return subject;
RACMulticastConnection • Signals start their work on each new subscription
– great for isolating work • but bad if you have heavy side effects • Made using -multicast: on RACSignal • Creates one and only one subscription
Example
Authentication
RACSignal *deferredToken = [RACSignal defer:^{ return [self authWithUsername:username key:password]; }];
_tokenConnection = [deferredToken multicast:[RACReplaySubject subject]]; - (RACSignal *)withAuthToken { [_tokenConnection connect]; return _tokenConnection.signal; } - (RACSignal *)getServers { return [[self withAuthToken] flattenMap:^RACSignal *(NSString *token) { return [self enqueueRequestWithMethod:@"GET" endpoints:self.computeEndpoints path:@"/servers/detail" parameters:nil]; }]; }
a GUI example
KVO
None
NSArray *fields = @[RACAble(self.password), RACAble(self.passwordConfirmation)]; RAC(self.createEnabled) = [RACSignal combineLatest:fields reduce:^(NSString
*password, NSString *passwordConfirm) { return [passwordConfirm isEqualToString:password]; }];
Notification Signals
None
RAC(self.logInButton.enabled) = [RACSignal combineLatest:@[ self.usernameTextField.rac_textSignal, self.passwordTextField.rac_textSignal] reduce:^(NSString *user, NSString *pass)
{ return (user.length > 0 && pass.length > 0); }];
Control Events
None
RACSignal *deleteSignal = [button rac_signalForControlEvents:UIControlEventTouchUpInside]; [deleteSignal subscribeNext:^(UIButton *sender) { [[self.server
delete] subscribeCompleted:deleteServer]; }];
None
None