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
630
Android Accessibility at GDG Devfest Brussels 2016
appfoundrybe
0
580
Other Decks in Programming
See All in Programming
CSC509 Lecture 01
javiergs
PRO
1
440
複雑化したリポジトリをなんとかした話 pipenvからuvによるモノレポ構成への移行
satoshi256kbyte
1
970
CSC305 Lecture 06
javiergs
PRO
0
210
Signals & Resource API in Angular: 3 Effective Rules for Your Architecture @BASTA 2025 in Mainz
manfredsteyer
PRO
0
110
私達はmodernize packageに夢を見るか feat. go/analysis, go/ast / Go Conference 2025
kaorumuta
2
510
いま中途半端なSwift 6対応をするより、Default ActorやApproachable Concurrencyを有効にしてからでいいんじゃない?
yimajo
2
390
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
160
Serena MCPのすすめ
wadakatu
4
940
なぜGoのジェネリクスはこの形なのか? Featherweight Goが明かす設計の核心
ryotaros
7
1.1k
uniqueパッケージの内部実装を支えるweak pointerの話
magavel
0
950
iOSエンジニア向けの英語学習アプリを作る!
yukawashouhei
0
190
CSC305 Lecture 03
javiergs
PRO
0
240
Featured
See All Featured
Music & Morning Musume
bryan
46
6.8k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
114
20k
Speed Design
sergeychernyshev
32
1.1k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.5k
Making the Leap to Tech Lead
cromwellryan
135
9.6k
Side Projects
sachag
455
43k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
248
1.3M
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
140
34k
Done Done
chrislema
185
16k
The Language of Interfaces
destraynor
162
25k
GitHub's CSS Performance
jonrohan
1032
460k
A better future with KSS
kneath
239
18k
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