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
190
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
730
Other Decks in Programming
See All in Programming
マイコンでもRustのtestがしたい その2/KernelVM Tokyo 18
tnishinaga
2
2.4k
250830 IaCの選定~AWS SAMのLambdaをECSに乗り換えたときの備忘録~
east_takumi
0
340
『リコリス・リコイル』に学ぶ!! 〜キャリア戦略における計画的偶発性理論と変わる勇気の重要性〜
wanko_it
1
620
令和最新版手のひらコンピュータ
koba789
14
8.2k
TROCCO×dbtで実現する人にもAIにもやさしいデータ基盤
nealle
0
390
時間軸から考えるTerraformを使う理由と留意点
fufuhu
5
270
パスタの技術
yusukebe
1
540
Rancher と Terraform
fufuhu
2
150
【第4回】関東Kaggler会「Kaggleは執筆に役立つ」
mipypf
0
950
ライブ配信サービスの インフラのジレンマ -マルチクラウドに至ったワケ-
mirrativ
2
270
Ruby Parser progress report 2025
yui_knk
1
240
Google I/O recap web編 大分Web祭り2025
kponda
0
2.9k
Featured
See All Featured
Fashionably flexible responsive web design (full day workshop)
malarkey
407
66k
Building a Modern Day E-commerce SEO Strategy
aleyda
43
7.5k
How STYLIGHT went responsive
nonsquared
100
5.8k
Code Reviewing Like a Champion
maltzj
525
40k
Facilitating Awesome Meetings
lara
55
6.5k
Designing for Performance
lara
610
69k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
229
22k
Raft: Consensus for Rubyists
vanstee
140
7.1k
4 Signs Your Business is Dying
shpigford
184
22k
GraphQLとの向き合い方2022年版
quramy
49
14k
YesSQL, Process and Tooling at Scale
rocio
173
14k
Building an army of robots
kneath
306
46k
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