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
350
Tetris Masterclass
robb
0
540
Other Decks in Programming
See All in Programming
コントリビューターによるDenoのすゝめ / Deno Recommendations by a Contributor
petamoriken
0
200
ThorVG Viewer In VS Code
nors
0
770
それ、本当に安全? ファイルアップロードで見落としがちなセキュリティリスクと対策
penpeen
7
2.4k
疑似コードによるプロンプト記述、どのくらい正確に実行される?
kokuyouwind
0
380
AI Schema Enrichment for your Oracle AI Database
thatjeffsmith
0
250
AIフル活用時代だからこそ学んでおきたい働き方の心得
shinoyu
0
130
Basic Architectures
denyspoltorak
0
660
Rust 製のコードエディタ “Zed” を使ってみた
nearme_tech
PRO
0
150
Architectural Extensions
denyspoltorak
0
280
登壇資料を作る時に意識していること #登壇資料_findy
konifar
4
1k
メルカリのリーダビリティチームが取り組む、AI時代のスケーラブルな品質文化
cloverrose
2
510
Apache Iceberg V3 and migration to V3
tomtanaka
0
150
Featured
See All Featured
Max Prin - Stacking Signals: How International SEO Comes Together (And Falls Apart)
techseoconnect
PRO
0
83
HDC tutorial
michielstock
1
360
Lightning talk: Run Django tests with GitHub Actions
sabderemane
0
110
Google's AI Overviews - The New Search
badams
0
900
Faster Mobile Websites
deanohume
310
31k
Exploring the relationship between traditional SERPs and Gen AI search
raygrieselhuber
PRO
2
3.6k
Building Applications with DynamoDB
mza
96
6.9k
Sam Torres - BigQuery for SEOs
techseoconnect
PRO
0
180
Bridging the Design Gap: How Collaborative Modelling removes blockers to flow between stakeholders and teams @FastFlow conf
baasie
0
440
How to make the Groovebox
asonas
2
1.9k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
54k
Into the Great Unknown - MozCon
thekraken
40
2.2k
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