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
160
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
680
Other Decks in Programming
See All in Programming
Recoilを剥がしている話
kirik
5
7.1k
Mermaid x AST x 生成AI = コードとドキュメントの完全同期への道
shibuyamizuho
1
230
今年のアップデートで振り返るCDKセキュリティのシフトレフト/2024-cdk-security-shift-left
tomoki10
0
230
テストケースの名前はどうつけるべきか?
orgachem
PRO
0
150
KubeCon + CloudNativeCon NA 2024 Overviewat Kubernetes Meetup Tokyo #68 / amsy810_k8sjp68
masayaaoyama
0
260
【re:Growth 2024】 Aurora DSQL をちゃんと話します!
maroon1st
0
800
create_tableをしただけなのに〜囚われのuuid編〜
daisukeshinoku
0
280
Cloudflare MCP ServerでClaude Desktop からWeb APIを構築
kutakutat
1
570
Kaigi on Railsに初参加したら、その日にLT登壇が決定した件について
tama50505
0
100
Итераторы в Go 1.23: зачем они нужны, как использовать, и насколько они быстрые?
lamodatech
0
940
開発者とQAの越境で自動テストが増える開発プロセスを実現する
92thunder
1
200
採用事例の少ないSvelteを選んだ理由と それを正解にするためにやっていること
oekazuma
2
1.1k
Featured
See All Featured
Code Reviewing Like a Champion
maltzj
521
39k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
29
910
A Tale of Four Properties
chriscoyier
157
23k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
8
1.2k
Documentation Writing (for coders)
carmenintech
66
4.5k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
38
1.9k
4 Signs Your Business is Dying
shpigford
182
21k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
28
2.1k
What's in a price? How to price your products and services
michaelherold
243
12k
Fantastic passwords and where to find them - at NoRuKo
philnash
50
2.9k
A Modern Web Designer's Workflow
chriscoyier
693
190k
Six Lessons from altMBA
skipperchong
27
3.5k
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