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
Streamlitで実現できるようになったこと、実現してくれたこと
ayumu_yamaguchi
2
270
[Codecon - 2025] Como não odiar seus testes
camilacampos
0
100
CEDEC 2025 『ゲームにおけるリアルタイム通信への QUIC導入事例の紹介』
segadevtech
2
750
Google I/O Extended Incheon 2025 ~ What's new in Android development tools
pluu
1
220
実践 Dev Containers × Claude Code
touyu
1
120
PHPカンファレンス関西2025 基調講演
sugimotokei
6
1.1k
あまり知られていない MCP 仕様たち / MCP specifications that aren’t widely known
ktr_0731
0
220
Flutterと Vibe Coding で個人開発!
hyshu
1
230
React は次の10年を生き残れるか:3つのトレンドから考える
oukayuka
41
16k
DatadogのArchived LogsをSnowflakeで高速に検索する方法(Archive Searchでオワコンにならないことを祈って) / How to search Datadog Archived Logs quickly with Snowflake (hoping Datadog Archive Search doesn’t make this obsolete)
civitaspo
0
110
それ CLI フレームワークがなくてもできるよ / Building CLI Tools Without Frameworks
orgachem
PRO
17
3.7k
変化を楽しむエンジニアリング ~ いままでとこれから ~
murajun1978
0
670
Featured
See All Featured
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
26k
Visualization
eitanlees
146
16k
Side Projects
sachag
455
43k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
46
7.5k
Building an army of robots
kneath
306
45k
For a Future-Friendly Web
brad_frost
179
9.9k
The Invisible Side of Design
smashingmag
301
51k
Faster Mobile Websites
deanohume
308
31k
Building Applications with DynamoDB
mza
95
6.5k
Why You Should Never Use an ORM
jnunemaker
PRO
58
9.5k
Testing 201, or: Great Expectations
jmmastey
45
7.6k
The Cost Of JavaScript in 2023
addyosmani
51
8.7k
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