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
GitHub Actions × AWS OIDC連携の仕組みと経緯を理解する
ota1022
0
230
階層構造を表現するデータ構造とリファクタリング 〜1年で10倍成長したプロダクトの変化と課題〜
yuhisatoxxx
3
870
Swiftビルド弾丸ツアー - Swift Buildが作る新しいエコシステム
giginet
PRO
0
1.6k
高度なUI/UXこそHotwireで作ろう Kaigi on Rails 2025
naofumi
4
3.1k
Let's Write a Train Tracking Algorithm
twocentstudios
0
220
Advance Your Career with Open Source
ivargrimstad
0
270
Local Peer-to-Peer APIはどのように使われていくのか?
hal_spidernight
2
440
Playwrightはどのようにクロスブラウザをサポートしているのか
yotahada3
7
2.2k
そのpreloadは必要?見過ごされたpreloadが技術的負債として爆発した日
mugitti9
2
2.8k
AIエージェント時代における TypeScriptスキーマ駆動開発の新たな役割
bicstone
4
1.4k
ИИ-Агенты в каждый дом – Алексей Порядин, PythoNN
sobolevn
0
150
10年もののAPIサーバーにおけるCI/CDの改善の奮闘
mbook
0
700
Featured
See All Featured
How to Think Like a Performance Engineer
csswizardry
27
2k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
127
53k
Statistics for Hackers
jakevdp
799
220k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
45
2.5k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
12
1.1k
Imperfection Machines: The Place of Print at Facebook
scottboms
269
13k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.5k
The Cult of Friendly URLs
andyhume
79
6.6k
The Invisible Side of Design
smashingmag
301
51k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
Automating Front-end Workflow
addyosmani
1371
200k
Measuring & Analyzing Core Web Vitals
bluesmoon
9
610
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