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
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
AppFoundry
April 11, 2014
Programming
84
2
Share
ReactiveCocoa
A brief overview of reactive programming and how it is applied to Objective C.
AppFoundry
April 11, 2014
More Decks by AppFoundry
See All by AppFoundry
Introductie iOS - Jens
appfoundrybe
0
110
Android In Practice
appfoundrybe
0
150
Android Introduction 3.0 by Siebe
appfoundrybe
0
140
Android in Practice (long)
appfoundrybe
0
220
React Native - cross-platform mobile app development
appfoundrybe
0
210
React Native Storybook
appfoundrybe
0
490
the ionic crash course
appfoundrybe
1
200
View based apps with Conductor
appfoundrybe
0
660
Android Accessibility at GDG Devfest Brussels 2016
appfoundrybe
0
680
Other Decks in Programming
See All in Programming
Oxcを導入して開発体験が向上した話
yug1224
4
280
関係性から理解する"同一性"の型用語たち
pvcresin
2
640
フロントエンドとバックエンドで「1文字」を揃えよう
youkidearitai
PRO
0
200
TSKaigi Night Talks 2026_TypeScriptでサプライチェーンの整合性を型に閉じ込める
geekplus_tech
0
300
Oxlintのカスタムルールの現況
syumai
5
1k
net-httpのHTTP/2対応について
naruse
0
440
ビジネスモデルから紐解く、AI+型駆動開発
hirokiomote
2
5.2k
脅威をエンジニアリングの糧にして――現場編 / Turning Threats into Engineering Fuel — Field Edition
nrslib
0
250
タクシーアプリ『GO』の バックエンド開発のおける AI利活用と若者のすべて
pyama86
3
1.9k
AIとRubyの静的型付け
ukin0k0
0
540
New "Type" system on PicoRuby
pocke
1
470
3Dシーンの圧縮
fadis
1
650
Featured
See All Featured
DBのスキルで生き残る技術 - AI時代におけるテーブル設計の勘所
soudai
PRO
65
55k
Agile Actions for Facilitating Distributed Teams - ADO2019
mkilby
0
200
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
141
35k
Building an army of robots
kneath
306
46k
Product Roadmaps are Hard
iamctodd
PRO
55
12k
Principles of Awesome APIs and How to Build Them.
keavy
128
17k
Designing for Performance
lara
611
70k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
16k
How STYLIGHT went responsive
nonsquared
100
6.2k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
1.9k
A Tale of Four Properties
chriscoyier
163
24k
The AI Search Optimization Roadmap by Aleyda Solis
aleyda
1
5.9k
Transcript
None
None
OVERVIEW ⇁ FUNCTIONAL REACTIVE PROGRAMMING ⇁ REACTIVECOCOA* ⇁ RESPONDER /
CALLHANDLE? ⇁ CODE EXAMPLES
REACTIVECOCOA* TOPICS ⇁ BUILDING BLOCKS ⇁ COLLECTION TRANSFORMATION ⇁ ASYNCHRONOUS
PROGRAMMING ⇁ COMPOSITION & PARALLELIZATION ⇁ DATA BINDING & MVVM
FUNCTIONAL REACTIVE PROGRAMMING First look at
FRP ❝FRP IS A HIGH-LEVEL WAY TO WORK WITH INTERACTIONS.
IT PROVIDES CONTROL FLOW STRUCTURES FOR TIME. IT IS BUILT AROUND THE IDEA OF TIME-VARYING VALUES, CALLED SIGNALS. ❞ — elm-lang.org
٩۹(๏̯͡๏)ゞ? WAIT. WHAT?!
FRP ❝REPRESENT & QUERY ASYNCHRONOUS DATA STREAMS, AND PARAMETERIZE THE
CONCURRENCY IN THE ASYNCHRONOUS DATA STREAMS USING SCHEDULERS.❞ — rx.codeplex.com
FUNCTIONAL REACTIVE INPUT ⤑ OUTPUT AVOID STATE AVOID MUTABLE DATA
NO SIDE-EFFECTS DECLARATIVE
FUNCTIONAL REACTIVE DATA FLOW CHANGE PROPAGATION SIDE-EFFECTS EVENTS NON-BLOCKING COMPOSITION
(-_-)ゞ
None
None
DIFFERENT PARADIGM NOT JUST A LIBRARY
PROCEDURAL (HOW?)
RISE OF FRP
ERIK MEIJER ⇁ FUNCTIONAL PROGRAMMING & COMPILER IMPLEMENTATION ⇁ MICROSOFT
(2000 – 2013) ⇁ REACTIVE EXTENSIONS (RX) FOR C#/.NET
WHAT’S THE DIFFERENCE BETWEEN
NOTHING.
BOTH ARE JUST
DB EXAMPLE [[[[db getArticles] filter:^BOOL(Article* article) { return article.isDraft; }]
map:^Draft*(Article* article) { Draft *draft = [Draft new]; draft.title = article.title; return draft; }] doNext:^(Draft *draft) { // Do something with each draft }];
TOUCH EXAMPLE [[[[view touchSignals] filter:^BOOL(UITouch* touch) { return touch.duration >
100; }] map:^TouchPoint*(UITouch* touch) { TouchPoint* tp = [TouchPoint new]; tp.x = touch.x; tp.y = touch.y; return tp; }] doNext:^(TouchPoint *tp) { // Do something with each tp }];
RX.NET REACTIVECOCOA RXJAVA* RXJS RXCPP RXPY RXRB BACONJS
FRP IN DESIGN PATTERNS 3-in-1
IENUMERATOR<T> ⇁ ENUMERABLE<T> bool MoveNext()
IOBSERVER<T> void OnCompleted() void OnError() void OnNext() OBSERVABLE<T> Disposable subscribe(Observer<T>)
DISPOSABLE void dispose()
SIGNAL IENUMERATOR<T> IOBSERVER<T> ENUMERABLE<T> DISPOSABLE OBSERVABLE<T>
REACTIVECOCOA Building Blocks
STREAM ⇁ ABSTRACT BASE TYPE ⇁ ANY SERIES OF OBJECT
VALUES ⇁ VALUES AVAILABLE NOW OR IN FUTURE RACStream
SIGNAL ⇁ PUSH-DRIVEN STREAM ⇁ DATA TO BE DELIVERED IN
THE FUTURE ⇁ VALUES SENT AS THEY ‘ARRIVE’ RACSignal A B
⇁ SUBSCRIBE TO RECEIVE EVENTS ⇁ SENDS 3 EVENT TYPES
⇁ ‘NEXT’ ⇁ ‘ERROR’ ⇁ ‘COMPLETE’ ⇁ IMMUTABLE A B
COLD ⇁ DEFAULT ⇁ START WORK WITH EACH NEW SUBSCRIPTION
RACSignal HOT ⇁ WORK STARTS ONCE ⇁ FOR ALL SUBSCRIPTIONS RACMultiCastConnection
SIDE-EFFECTS ⇁ WORK THAT HAPPENS AS SIGNALS MOVE THROUGH ⇁
NEXT ⇁ ERROR ⇁ COMPLETE ⇁ UI ⇁ FIRING OTHER SIGNALS ⇁ …
SEQUENCE ⇁ PULL-DRIVEN STREAM ⇁ DATA ALREADY AVAILABLE ⇁ VALUES
REQUESTED LAZILY RACSequence
SUBJECT ⇁ INHERITS FROM SIGNAL ⇁ MUTABLE ⇁ ‘NEXT’, ‘ERROR’,
‘COMPLETE’ EVENTS FROM OUTSIDE ⇁ BRIDGE NON-REACTIVE CODE RACSubject
SUBSCRIPTION ⇁ WAITS FOR EVENTS FROM A SIGNAL ⇁ DISPOSED
WHEN SIGNAL COMPLETES/ERRORS id<RACSubscriber>
DISPOSABLE ⇁ CANCELLATION & RESOURCE CLEANUP ⇁ UNSUBSCRIBES FROM SIGNALS
⇁ IMPLICIT OR EXPLICIT ⇁ RESULT OF A SUBSCRIPTION RACDisposable
SCHEDULER ⇁ (SERIAL) EXECUTION QUEUE FOR SIGNALS ⇁ SIMILAR TO THREADS
⇁ SUPPORTS CANCELLATION ⇁ NO SYNCHRONOUS EXECUTION ⇁ PREVENTS DEADLOCKS RACScheduler
⇁ CREATES & SUBSCRIBES TO A SIGNAL ⇁ IN RESPONSE
TO UI ACTION ⇁ TYPICAL USES ⇁ HANDLERS ⇁ VIEWMODELS COMMAND RACCommand
BUTTON TAP SVC CALL FILTER MAP ARRAY à UI FLATTENMAP
FILTER
SIGNAL OPERATIONS ⇁ -CONCAT: ⇁ -MERGE: ⇁ -FLATTENMAP: ⇁ -THEN:
SIGNAL OPERATIONS ⇁ -RETRY: ⇁ -IF:THEN:ELSE ⇁ -DELAY: ⇁ -THROTTLE: ⇁ -TAKE: ⇁ -TRY:CATCH: ⇁ +RETURN: operators
COLLECTION TRANSFORMATION
COLLECTION TRANSFORMATION ⇁ HIGHER ORDER FUNCTIONS ⇁ MAP ⇁ FILTER
⇁ FOLD ⇁ REDUCE
EXAMPLE NSArray *got = @[@”Tyrion”, @”Jaime”, @”Daenerys”, @”Jon”]; NSMutableArray *gotPeople
= [[NSMutableArray alloc] init]; for(NSString *name in got) { if([name hasPrefix:@”J”]) { continue; } Person *p = [Person new]; p.name = name; [gotPeople addObject:p] }
EXAMPLE NSArray *got = @[@”Tyrion”, @”Jaime”, @”Daenerys”, @”Jon”]; [[got.rac_sequence filter:^BOOL(NSString
*name) { return [name hasPrefix:@”J”]; }] map:^Person*(NSString *name) { Person *p = [Person new]; p.name = name; return p; }];
ASYNCHRONOUS PROGRAMMING
MODELS ⇁ EVENT-DRIVEN / CALLBACK-BASED ⇁ INTERRUPTS FLOW ⇁ NESTING
= PROBLEMATIC ⇁ FUTURES / PROMISES ⇁ ENCAPSULATES SUCCESS / FAILURE HANDLERS ⇁ SOME SEQUENCING & PARALLELISM ⇁ BOTH: REPRESENT SINGLE VALUES
SIGNALS ⇁ LINEAR FLOW (LIMITED NESTING) ⇁ ENCAPSULATES STREAM OF
VALUES OVER TIME ⇁ INFINITELY COMPOSABLE ⇁ SIMPLIFIED SEQUENCING & PARALLELIZATION ⇁ SERIAL QUEUE
EXAMPLE [[[[[self.service getUpcomingMeetings] collect] doNext:^(NSArray *upcomingMeetings) { self.upcomingMeetings = upcomingMeetings;
}] doError:^(NSError *error) { [[AlertView alertWithError:error] show]; }] subscribeCompleted:^{ [self.tableView reloadData]; }];
EXAMPLE [[[[[self.service getUpcomingMeetings] collect] doNext:^(NSArray *upcomingMeetings) { self.upcomingMeetings = upcomingMeetings;
}] doError:^(NSError *error) { [[AlertView alertWithError:error] show]; }] subscribeCompleted:^{ [self.tableView reloadData]; }]; SIGNAL SUBSCRIPTION SIDE-‐EFFECT SIDE-‐EFFECT OPERATION (return) DISPOSABLE
COMPOSITION & PARALLELIZATION
COMPOSITION ⇁ DEPENDENT TASKS ⇁ E.G. NETWORK REQUESTS ⇁ SIGNAL
CHAINING ⇁ NESTING
COMPOSITION – EXAMPLE [client logInWithSuccess:^{ [client loadCachedMessagesWithSuccess:^(NSArray *messages) { [client
fetchMessagesAfterMessage:messages.lastObject success:^(NSArray *nextMessages) { NSLog(@"Fetched all messages."); } failure:^(NSError *error) { [self presentError:error]; }]; } failure:^(NSError *error) { [self presentError:error]; }]; } failure:^(NSError *error) { [self presentError:error]; }];
COMPOSITION – EXAMPLE [[[[client logIn] then:^{ return [client loadCachedMessages]; }]
flattenMap:^(NSArray *messages) { return [client fetchMessages:messages.lastObject]; }] subscribeError:^(NSError *error) { [self presentError:error]; } completed:^{ NSLog(@"Fetched all messages."); }];
PARALLELIZATION ⇁ ONE-BY-ONE ⇁ [RACSignal -concat:@[signals ]] ⇁ IN PARALLEL ⇁ [RACSignal
-combineLatest:@[signals ]] ⇁ RETURN TYPES? JUST SIGNALS.
DATA BINDING & MVVM ReactiveCocoa
DATA BINDING ⇁ NON-STANDARD ON IOS ⇁ REPLACEMENT FOR KEY-VALUE
OBSERVING (KVO) ⇁ TURNS REGULAR PROPERTIES INTO SIGNALS
DATA BINDING [[RACObserve(self, username) filter:^(NSString *newName) { return [newName hasPrefix:@"j"];
}] subscribeNext:^(NSString *newName) { NSLog(@"%@", newName); }];
MVVM VIEW VIEWMODEL MODEL NOTIFIES COMMANDS REFERENCES
RESPONDER / CALLHANDLE ?
CODE EXAMPLES