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
AppFoundry
April 11, 2014
Programming
2
74
ReactiveCocoa
A brief overview of reactive programming and how it is applied to Objective C.
AppFoundry
April 11, 2014
Tweet
Share
More Decks by AppFoundry
See All by AppFoundry
Introductie iOS - Jens
appfoundrybe
0
100
Android In Practice
appfoundrybe
0
140
Android Introduction 3.0 by Siebe
appfoundrybe
0
110
Android in Practice (long)
appfoundrybe
0
200
React Native - cross-platform mobile app development
appfoundrybe
0
170
React Native Storybook
appfoundrybe
0
460
the ionic crash course
appfoundrybe
1
180
View based apps with Conductor
appfoundrybe
0
640
Android Accessibility at GDG Devfest Brussels 2016
appfoundrybe
0
600
Other Decks in Programming
See All in Programming
O Que É e Como Funciona o PHP-FPM?
marcelgsantos
0
250
CSC305 Lecture 14
javiergs
PRO
0
210
CSC509 Lecture 10
javiergs
PRO
0
160
KoogではじめるAIエージェント開発
hiroaki404
1
290
Software Architecture
hschwentner
6
2.4k
CSC305 Lecture 10
javiergs
PRO
0
330
HTTPじゃ遅すぎる! SwitchBotを自作ハブで動かして学ぶBLE通信
occhi
0
180
alien-signals と自作 OSS で実現する フレームワーク非依存な ロジック共通化の探求 / Exploring Framework-Agnostic Logic Sharing with alien-signals and Custom OSS
aoseyuu
3
5.5k
SwiftDataを使って10万件のデータを読み書きする
akidon0000
0
250
Node-REDのノードの開発・活用事例とコミュニティとの関わり(Node-RED Con Nagoya 2025)
404background
0
110
エンジニアインターン「Treasure」とHonoの2年、そして未来へ / Our Journey with Hono Two Years at Treasure and Beyond
carta_engineering
0
480
AIと人間の共創開発!OSSで試行錯誤した開発スタイル
mae616
2
870
Featured
See All Featured
Intergalactic Javascript Robots from Outer Space
tanoku
273
27k
Making Projects Easy
brettharned
120
6.4k
It's Worth the Effort
3n
187
28k
YesSQL, Process and Tooling at Scale
rocio
174
15k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
31
2.7k
Balancing Empowerment & Direction
lara
5
710
A Tale of Four Properties
chriscoyier
161
23k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
21
1.2k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
15k
Speed Design
sergeychernyshev
32
1.2k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
658
61k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
1.7k
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