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.8k
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
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
360
Tetris Masterclass
robb
0
540
Other Decks in Programming
See All in Programming
車輪の再発明をしよう!PHP で実装して学ぶ、Web サーバーの仕組みと HTTP の正体
h1r0
2
300
生成 AI 時代のスナップショットテストってやつを見せてあげますよ(α版)
ojun9
0
290
Angular-Apps smarter machen mit Gen AI: Lokal und offlinefähig - Hands-on Workshop!
christianliebel
PRO
0
130
CSC307 Lecture 15
javiergs
PRO
0
260
存在論的プログラミング: 時間と存在を記述する
koriym
4
380
[PHPerKaigi 2026]PHPerKaigi2025の企画CodeGolfが最高すぎて社内で内製して半年運営して得た内製と運営の知見
ikezoemakoto
0
250
メタプログラミングで実現する「コードを仕様にする」仕組み/nikkei-tech-talk43
nikkei_engineer_recruiting
0
210
Ruby and LLM Ecosystem 2nd
koic
1
1.2k
What Spring Developers Should Know About Jakarta EE
ivargrimstad
0
760
Cyrius ーLinux非依存にコンテナをネイティブ実行する専用OSー
n4mlz
0
230
Feature Toggle は捨てやすく使おう
gennei
0
240
ポーリング処理廃止によるイベント駆動アーキテクチャへの移行
seitarof
3
1.1k
Featured
See All Featured
How to Ace a Technical Interview
jacobian
281
24k
Test your architecture with Archunit
thirion
1
2.2k
Build your cross-platform service in a week with App Engine
jlugia
234
18k
The Language of Interfaces
destraynor
162
26k
Context Engineering - Making Every Token Count
addyosmani
9
770
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
199
73k
AI Search: Implications for SEO and How to Move Forward - #ShenzhenSEOConference
aleyda
1
1.2k
The innovator’s Mindset - Leading Through an Era of Exponential Change - McGill University 2025
jdejongh
PRO
1
130
From Legacy to Launchpad: Building Startup-Ready Communities
dugsong
0
180
Agile that works and the tools we love
rasmusluckow
331
21k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
38
2.8k
Facilitating Awesome Meetings
lara
57
6.8k
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