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
ReactiveCocoa
Search
Robert Böhnke
May 02, 2013
Programming
19
2.7k
ReactiveCocoa
My talk for UIKonf 2013 about ReactiveCocoa and how to get rid of state
Robert Böhnke
May 02, 2013
Tweet
Share
More Decks by Robert Böhnke
See All by Robert Böhnke
Brooklyn iOS Developer Meetup February 2014
robb
8
3k
Cocoa Kucha Berlin 2013
robb
2
2.1k
ReactiveCocoa NSSpain
robb
18
2.4k
Underscore.m + Asterism
robb
4
1.2k
Super Mario Masterclass
robb
2
320
Tetris Masterclass
robb
0
520
Other Decks in Programming
See All in Programming
KawaiiLT 登壇資料 キャリアとモチベーション
hiiragi
0
120
On-the-fly Suggestions of Rewriting Method Deprecations
ohbarye
1
2.6k
Golangci-lint v2爆誕: 君たちはどうすべきか
logica0419
1
120
ウォンテッドリーの「ココロオドル」モバイル開発 / Wantedly's "kokoro odoru" mobile development
kubode
1
140
新しいPHP拡張モジュールインストール方法「PHP Installer for Extensions (PIE)」を使ってみよう!
cocoeyes02
0
400
「理解」を重視したAI活用開発
fast_doctor
0
100
Compose Hot Reload is here, stop re-launching your apps! (Android Makers 2025)
zsmb
1
520
Agentic Applications with Symfony
el_stoffel
2
310
国漢文混用体からHolloまで
minhee
1
190
AI時代の開発者評価について
ayumuu
0
150
「影響が少ない」を自分の目でみてみる
o0h
PRO
2
1.1k
Empowering Developers with HTML-Aware ERB Tooling @ RubyKaigi 2025, Matsuyama, Ehime
marcoroth
2
730
Featured
See All Featured
How to Ace a Technical Interview
jacobian
276
23k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
30
2k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
178
53k
Why Our Code Smells
bkeepers
PRO
336
57k
Mobile First: as difficult as doing things right
swwweet
223
9.6k
Documentation Writing (for coders)
carmenintech
69
4.7k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
26k
Intergalactic Javascript Robots from Outer Space
tanoku
270
27k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
41
2.2k
Producing Creativity
orderedlist
PRO
344
40k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
34
2.2k
Fireside Chat
paigeccino
37
3.4k
Transcript
ReactiveCocoa OR: How I stopped worrying about state and love
FRP
✉ robb
[email protected]
tmp ceterum_censeo
Let’s talk about State
evil √
Have you tried turning it off and on again?
Have you tried turning it off and on again? Have
you tried turning it off and on again?
state
@property (readwrite, …) BOOL quacksLikeADuck; @property (readwrite, …) BOOL walksLikeADuck;
@property (readonly, …) BOOL probablyADuck;
+ (NSSet *)keyPathsForValuesAffectingProbablyADuck { return [NSSet setWithObjects:@”walksLikeADuck”, @”quacksLikeADuck”, nil]; }
- (BOOL)isProbablyADuck { return _quacksLikeADuck && _walksLikeADuck; }
ReactiveCocoa
RAC(self.probablyADuck) = [RACSignal combineLatest:@[ RACAbleWithStart(self.walksLikeADuck), RACAbleWithStart(self.quacksLikeADuck) ] reduce:^(NSNumber *walks, NSNumber
*quacks) { return @(walks.boolValue && quaks.boolValue); }];
None
[self.usernameField addTarget:self action:@selector(textFieldDidUpdate:) forControlEvents:UIControlEventEditingChanged]; [self.emailField addTarget:self action:@selector(textFieldDidUpdate:) forControlEvents:UIControlEventEditingChanged]; - (void)textFieldDidUpdate:(UITextField
*)textField { BOOL validUsername = self.usernameField.text.length > 0; BOOL validEmail = [self.emailField.text uik_isEmail]; self.signupButton.enabled = validEmail && validUsername; }
because programming
[self.usernameField addTarget:self action:@selector(textFieldDidUpdate:) forControlEvents:UIControlEventEditingChanged]; [self.emailField addTarget:self action:@selector(textFieldDidUpdate:) forControlEvents:UIControlEventEditingChanged]; - (void)textFieldDidUpdate:(UITextField
*)textField { BOOL validUsername = self.usernameField.text.length > 0; BOOL validEmail = [self.emailField.text uik_isEmail]; self.signupButton.enabled = validEmail && validUsername; }
RAC(self.signupButton.enabled) = [RACSignal combineLatest:@[ self.usernameField.rac_textSignal, self.emailField.rac_textSignal ] reduce:^(NSString *username, NSString
*email) { BOOL validUsername = username.length > 0; BOOL validEmail = [email uik_isEmail]; return @(validUsername && validEmail); }];
FRP
None
None
ReactiveCocoa
@YES @NO @YES RACSignal
<UIControlEventEditingChanged> RACSignal
{“json_string”: “ohai”} RACSignal
RACSignal - (void)sendNext:(id)value; - (void)sendCompleted; - (void)sendError:(NSError *)error;
so, what?
map, reduce, filter
Let’s talk about Asynchrony
None
Blocks are awesome
void (^cb)(id operation, id result); void (^cb)(id operation, NSError *error);
void (^cb)(id result, NSError *error); void (^cb)(NSError *error, id result);
[client logIn:^{ [client loadMeUser:^(UIKUser *user) { [client loadNewslettersForUser:user success:^(NSArray *result)
NSLog(@"Your newsletters: %@", array); } failure:^(NSError *error) { // … }]; } failure:^(NSError *error) { // … }]; } failure:^(NSError *error) { // … }];
RACSignal
- (RACSignal *)logIn; - (RACSignal *)loadMeUser; - (RACSignal *)loadNewslettersForUser:(…)user;
[[[[client logIn] sequenceNext:^{ return [client loadMeUser]; }] flattenMap:^(UIKUser *user) {
return [client loadNewslettersForUser:user]; }] subscribeNext:^(NSArray *newsletters) { NSLog(@"Your newsletters: %@", newsletters); } error:^(NSError *error) { // … }];
None
- (RACSignal *)validateEmail:(NSString *)email;
RACSignal *validEmail = [[self.emailField.rac_textSignal map:^(NSString *email) { return [[client validateEmail:email]
startWith:@NO]; }] switchToLatest]; RACSignal *validForm = [RACSignal combineLatest:@[ validUsername, validEmail ] reduce:^(NSNumber *a, NSNumber *b) { return @(a.boolValue && b.boolValue); }]; RAC(self.signupButton.enabled) = validForm;
None
where's the catch?
•conceptual overhead •debugging can get tricky (logAll is your friend)
•forces you to think
should I use it?
Probably!
state
None