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
2.8k
19
Share
ReactiveCocoa
My talk for UIKonf 2013 about ReactiveCocoa and how to get rid of state
Robert Böhnke
May 02, 2013
More Decks by Robert Böhnke
See All by Robert Böhnke
Brooklyn iOS Developer Meetup February 2014
robb
8
3.2k
Cocoa Kucha Berlin 2013
robb
2
2.1k
ReactiveCocoa NSSpain
robb
18
2.5k
Underscore.m + Asterism
robb
4
1.3k
Super Mario Masterclass
robb
2
370
Tetris Masterclass
robb
0
550
Other Decks in Programming
See All in Programming
サークル参加から学ぶ、小さな事業の回し方
yuzneri
0
240
密結合なバックエンドから TypeScript のコードを生成する
kemuridama
1
360
Skillは並べた。動かなかった。契約で繋いだ。— 65個のSkillから、自走する開発サイクルへ
junholee
0
760
ふつうのFeature Flag実践入門
irof
6
3k
Kubernetesを使わない環境にもCloud Nativeなデプロイを実現する / Enabling Cloud Native deployments without the complexity of Kubernetes
linyows
3
570
Agentic UI beyond Chats Architecture Patterns & Open Standards @ngMunich 05/2026
manfredsteyer
PRO
0
150
AI時代の仕事技芸論 — ソフトウェア開発で「遊ぶように働く」職人的熟達のすすめ
kuranuki
0
120
CLIであることを活かしたGitHub Copilot CLI活用術 / GitHub Copilot CLI Pro Tips & Tricks
nao_mk2
1
1.1k
~ 秘伝のタレ化した『神スプシ』と戦う ~ 関数型パラダイムで壊れない仕組みへ
h0r15h0
1
130
New "Type" system on PicoRuby
pocke
1
200
関係性から理解する"同一性"の型用語たち
pvcresin
2
560
AIとRubyの静的型付け
ukin0k0
0
130
Featured
See All Featured
Thoughts on Productivity
jonyablonski
76
5.2k
Believing is Seeing
oripsolob
1
130
How to Get Subject Matter Experts Bought In and Actively Contributing to SEO & PR Initiatives.
livdayseo
0
130
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
46
2.8k
Crafting Experiences
bethany
1
160
What does AI have to do with Human Rights?
axbom
PRO
1
2.2k
We Are The Robots
honzajavorek
0
230
Tell your own story through comics
letsgokoyo
1
930
Bridging the Design Gap: How Collaborative Modelling removes blockers to flow between stakeholders and teams @FastFlow conf
baasie
0
560
AI Search: Implications for SEO and How to Move Forward - #ShenzhenSEOConference
aleyda
1
1.2k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
1.9k
The AI Revolution Will Not Be Monopolized: How open-source beats economies of scale, even for LLMs
inesmontani
PRO
3
3.5k
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