Lock in $30 Savings on PRO—Offer Ends Soon! ⏳
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
Basic Architectures
denyspoltorak
0
110
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
310
re:Invent 2025 のイケてるサービスを紹介する
maroon1st
0
150
JETLS.jl ─ A New Language Server for Julia
abap34
2
440
Context is King? 〜Verifiability時代とコンテキスト設計 / Beyond "Context is King"
rkaga
10
1.4k
DevFest Android in Korea 2025 - 개발자 커뮤니티를 통해 얻는 가치
wisemuji
0
170
認証・認可の基本を学ぼう前編
kouyuume
0
270
クラウドに依存しないS3を使った開発術
simesaba80
0
150
ELYZA_Findy AI Engineering Summit登壇資料_AIコーディング時代に「ちゃんと」やること_toB LLMプロダクト開発舞台裏_20251216
elyza
2
590
組み合わせ爆発にのまれない - 責務分割 x テスト
halhorn
1
160
生成AIを利用するだけでなく、投資できる組織へ
pospome
2
400
AI Agent Dojo #4: watsonx Orchestrate ADK体験
oniak3ibm
PRO
0
110
Featured
See All Featured
Pawsitive SEO: Lessons from My Dog (and Many Mistakes) on Thriving as a Consultant in the Age of AI
davidcarrasco
0
37
Unsuck your backbone
ammeep
671
58k
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
57
37k
Test your architecture with Archunit
thirion
1
2.1k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.6k
Done Done
chrislema
186
16k
Rebuilding a faster, lazier Slack
samanthasiow
85
9.3k
Bioeconomy Workshop: Dr. Julius Ecuru, Opportunities for a Bioeconomy in West Africa
akademiya2063
PRO
0
31
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
10
750
Java REST API Framework Comparison - PWX 2021
mraible
34
9k
Leveraging LLMs for student feedback in introductory data science courses - posit::conf(2025)
minecr
0
88
How Fast Is Fast Enough? [PerfNow 2025]
tammyeverts
3
400
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