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
RACDC – RACify
Search
Dave Lee
September 09, 2014
Programming
1
180
RACDC – RACify
A run through examples of building ReactiveCocoa APIs out of traditional objective-c APIs.
Dave Lee
September 09, 2014
Tweet
Share
More Decks by Dave Lee
See All by Dave Lee
Advanced Debugging & Swift
kastiglione
2
720
Other Decks in Programming
See All in Programming
Perlで痩せる
yuukis
1
680
GoのWebAssembly活用パターン紹介
syumai
3
10k
インターフェース設計のコツとツボ
togishima
2
710
try-catchを使わないエラーハンドリング!? PHPでResult型の考え方を取り入れてみよう
kajitack
3
510
既存デザインを変更せずにタップ領域を広げる方法
tahia910
1
210
Beyond Portability: Live Migration for Evolving WebAssembly Workloads
chikuwait
0
350
エラーって何種類あるの?
kajitack
5
140
「ElixirでIoT!!」のこれまでとこれから
takasehideki
0
350
Java on Azure で LangGraph!
kohei3110
0
120
F#で自在につくる静的ブログサイト - 関数型まつり2025
pizzacat83
0
290
Perplexity Slack Botを作ってAI活用を進めた話 / AI Engineering Summit プレイベント
n3xem
0
650
事業戦略を理解してソフトウェアを設計する
masuda220
PRO
22
6k
Featured
See All Featured
A Modern Web Designer's Workflow
chriscoyier
693
190k
VelocityConf: Rendering Performance Case Studies
addyosmani
329
24k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
46
9.6k
Typedesign – Prime Four
hannesfritz
42
2.7k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
32
5.9k
Statistics for Hackers
jakevdp
799
220k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
8
650
Intergalactic Javascript Robots from Outer Space
tanoku
271
27k
StorybookのUI Testing Handbookを読んだ
zakiyama
30
5.8k
Documentation Writing (for coders)
carmenintech
71
4.9k
The World Runs on Bad Software
bkeepers
PRO
68
11k
Building Adaptive Systems
keathley
43
2.6k
Transcript
RACify Dave Lee @kastiglione RACDC 2014
RACSignalify
Stealth Signals • Blocks • Delegates • Notifications • Errors
• Target-Action • KVO • Method Overriding
Bridging the Gap • +[RACSignal defer:] • -‐[NSNotificationCenter rac_addObserverForName:object:]
• -‐[NSObject rac_signalForSelector:] • +[RACSignal createSignal:] • RACObserve()
[RACSignal new]
[RACSignal return:value]
[RACSignal error:error]
[RACSignal empty]
[RACSubject subject]
+[RACSignal defer:] [RACSignal defer:^{ return [RACSignal return:@(arc4random())];
}]
+[RACSignal defer:] [RACSignal defer:^{ // Perform per-‐subscription side
effects. u_int32_t r = arc4random(); ! // Start (and in this case complete) the signal. return [RACSignal return:@(r)]; }]
+[RACSignal createSignal:] [RACSignal createSignal:^(id<RACSubscriber subscriber) { // Perform
per-‐subscription side effects. u_int32_t r = arc4random(); ! // Start (and in this case complete) the signal. [subscriber sendNext:@(r)]; [subscriber sendCompleted]; ! return (RACDisposable *)nil; }]
+[RACSignal createSignal:] [RACSignal createSignal:^(id<RACSubscriber subscriber) { return (RACDisposable
*)nil; }] [RACSignal empty]
AFNetworking
AFHTTPRequestOperationManager *manager = …; [manager GET:URLString parameters:params
success:^(AFHTTPRequestOperation *op, id response) { // Success-‐y } failure:^(AFHTTPRequestOperation *op, NSError *e) { // Fail-‐y }];
[RACSignal createSignal:^(id<RACSubscriber subscriber) { [manager GET:URLString parameters:params
success:^(AFHTTPRequestOperation *op, id response) { [subscriber sendNext:response]; [subscriber sendCompleted]; } failure:^(AFHTTPRequestOperation *op, NSError *e) { [subscriber sendError:e]; }]; }]
[RACSignal createSignal:^(id<RACSubscriber subscriber) { NSOperation *operation = [manager
GET:URLString parameters:params success:^(AFHTTPRequestOperation *op, id response) { [subscriber sendNext:response]; [subscriber sendCompleted]; } failure:^(AFHTTPRequestOperation *op, NSError *e) { [subscriber sendError:e]; }]; ! return [RACDisposable disposableWithBlock:^{ [operation cancel]; }]; }]
Core Data
__block NSArray *results; [managedObjectContext performBlock:^{ NSError *error;
results = [managedObjectContext executeFetchRequest:fetchRequest error:&error]; }];
[RACSignal createSignal:^(id<RACSubscriber> subscriber) { RACDisposable *disposable = [RACDisposable
new]; ! [managedObjectContext performBlock:^{ if (disposable.disposed) return; ! NSError *error; NSArray *results = [managedObjectContext performFetch:fetchRequest error:&error]; ! if (results != nil) { [subscriber sendNext:results]; [subscriber sendCompleted]; } else { [subscriber sendError:error]; } }];
! [managedObjectContext performBlock:^{ if (disposable.disposed) return;
! NSError *error; NSArray *results = [managedObjectContext performFetch:fetchRequest error:&error]; ! if (results != nil) { [subscriber sendNext:results]; [subscriber sendCompleted]; } else { [subscriber sendError:error]; } }]; ! return disposable; }];
Core Location
CLLocationManager *locationManager = … locationManager.delegate = self; static
volatile int32_t subscriberCount = 0;
[RACSignal createSignal:^(id<RACSubscriber> subscriber) { RACSignal *locations = [[self
rac_signalForSelector:@selector(…didUpdateLocations:) fromProtocol:@protocol(CLLocationManagerDelegate)] reduceEach:^(id _,NSArray *locations) { return locations; }]; ! RACSignal *error = [[[[self rac_signalForSelector:@selector(…didFailWithError:) fromProtocol:@protocol(CLLocationManagerDelegate)] reduceEach:^(id _, NSError *error) { return error; }] filter:^ BOOL (NSError *error) { // Documentation says Core Location will keep // will keep trying after kCLErrorLocationUnknown. return error.code != kCLErrorLocationUnknown;
RACSignal *error = [[[[self rac_signalForSelector:@selector(…didFailWithError:)
fromProtocol:@protocol(CLLocationManagerDelegate)] reduceEach:^(id _, NSError *error) { return error; }] filter:^ BOOL (NSError *error) { // Documentation says Core Location will keep // will keep trying after kCLErrorLocationUnknown. return error.code != kCLErrorLocationUnknown; }] flattenMap:^(NSError *error) { return [RACSignal error:error]; }]; ! RACDisposable *disposable = [[RACSignal merge:@[ locations, error ]] subscribe:subscriber];
RACDisposable *disposable = [[RACSignal
merge:@[ locations, error ]] subscribe:subscriber]; ! if (OSAtomictIncrement32(&subscriberCount) == 1) { [locationManager startUpdatingLocation]; } else { [subscriber sendNext:locationManager.location]; } ! return [RACDisposable disposableWithBlock:^{ [disposable dispose]; if (OSAtomictDecrement32(&subscriberCount) == 0) { [locationManager stopUpdatingLocation]; } }]; }];
AFNetworking
! RACSignal *isReachable = [RACObserve( reachabilityManager, networkReachabilityStatus)
map:^(NSNumber *networkReachabilityStatus) { switch (networkReachabilityStatus.intValue) { case AFNetworkReachabilityStatusReachableViaWWAN: case AFNetworkReachabilityStatusReachableViaWiFi: return @YES; } return @NO; }];
Notifications
UIApplicationWillEnterForegroundNotification UIApplicationDidEnterBackgroundNotification UIApplicationWillResignActiveNotification UIApplicationDidBecomeActiveNotification
RACSignal *isForeground = [RACSignal merge:@[ [[defaultCenter
rac_addObserverForName:WillEnterForeground …] mapReplace:@YES] [[defaultCenter rac_addObserverForName:DidEnterBackground …] mapReplace:@NO] ]]; ! RACSignal *hasLaunchedActive = [RACSignal if:isForeground then:[[defaultCenter rac_addObserverForName:DidBecomeActive …] take:1] else:[RACSignal empty]];
More… • Use -‐rac_signalForSelector:, everywhere. • Check out the AppKit
and UIKit extensions in RAC