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
240
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
ログラスを支える設計標準について / loglass-design-standards
urmot
10
2.1k
Build with AI 2024 Seoul - 제로부터 시작하는 Flutter with Gemini 생활 - 박제창
itsmedreamwalker
0
200
Prepare for Jakarta EE 11 - Performance and Developer Productivity
ivargrimstad
0
400
Zero Waste, Radical Magic, and Italian Graft – Quarkus Efficiency Secrets
hollycummins
0
210
educure_カリキュラム生操作マニュアル.pdf
linew_official
0
430
pixivアプリでマルチモジュールを実現するまで
gatosyocora
1
130
入門 AWS Amplify Gen2 / Introduction to AWS Amplify Gen2
genkiogasawara
1
310
スクラムガイドのスプリントレトロスペクティブを改めて読みかえしてみた / Re-reading the Sprint Retrospective Section in the Scrum Guide
mackey0225
3
320
"config" ってなんだ? / What is "config"?
okashoi
0
210
脱・初心者!脱・マネコン!AWS CDKを使ってみませんか!?
har1101
0
300
What We Can Learn From OSS
inouehi
0
400
データアナリストが行うDatabricksを活用したETLの自動化事例
shinoa
0
250
Featured
See All Featured
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
352
28k
Building Your Own Lightsaber
phodgson
97
5.7k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
29
6k
Stop Working from a Prison Cell
hatefulcrawdad
265
19k
How To Stay Up To Date on Web Technology
chriscoyier
781
250k
ParisWeb 2013: Learning to Love: Crash Course in Emotional UX Design
dotmariusz
103
6.6k
Become a Pro
speakerdeck
PRO
9
4.5k
Building a Modern Day E-commerce SEO Strategy
aleyda
16
6.3k
5 minutes of I Can Smell Your CMS
philhawksworth
199
19k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
226
16k
Practical Orchestrator
shlominoach
181
9.7k
A Tale of Four Properties
chriscoyier
150
22k
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