reactivecocoa in practice · why reactivecocoa? “instead of telling a computer how to do it’s...
TRANSCRIPT
![Page 1: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/1.jpg)
ReactiveCocoa in Practice
![Page 2: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/2.jpg)
Jeames Bone Mark Corbyn@outware
www.outware.com.au@jeamesbone @markcorbyn
![Page 3: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/3.jpg)
ReactiveCocoa
![Page 4: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/4.jpg)
What is ReactiveCocoa?
Functional Reactive Programming (FRP) framework
for iOS and OSX applications.
![Page 5: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/5.jpg)
Why ReactiveCocoa?
“Instead of telling a computer how to do it’s job, why don’t we just tell it
what it’s job is, and let it figure the rest out.”
![Page 6: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/6.jpg)
ReactiveCocoa in a Nutshell
The main component in ReactiveCocoa is the Signal.
Signals represent streams of values over time.
1 3 2 T
![Page 7: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/7.jpg)
Signals
h he hel T
[textField.rac_textSignal subscribeNext:^(NSString *text) { NSLog(@"text: ‘%@’", text);}];
> text: ‘h’> text: ‘he’> text: ‘hel’
![Page 8: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/8.jpg)
Operators
1 3 2
[signalA map:^(NSNumber *num) {return num * 10;
}];
10 30 20
![Page 9: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/9.jpg)
Operators
1 3 2
[signalA filter:^(NSNumber *num) {return num < 3;
}];
1 2
![Page 10: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/10.jpg)
Operators
a b c
1 3 2
[signalA merge:signalB]
1 3 2a b c
![Page 11: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/11.jpg)
What’s Next?
?
![Page 12: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/12.jpg)
1. Reactive View Controller
2. Reactive Notifications
3. Functional Data Processing
![Page 13: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/13.jpg)
Something SimpleAuthentication
/// Stores authentication credentials and tells us if we're authenticated.@protocol AuthStore <NSObject>
@property (nonatomic, readonly) BOOL authenticated;
- (void)storeAccessCredentials:(AccessCredentials *)accessCredentials;- (nullable AccessCredentials *)retrieveAccessCredentials;- (void)removeAccessCredentials;
@end
![Page 14: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/14.jpg)
Observe Authentication Changes
RACSignal *auth = RACObserve(authStore, authenticated);
YES NO YES
![Page 15: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/15.jpg)
Select the Right View Controller
RACSignal *authSignal = RACObserve(authStore, authenticated)
// Pick a view controllerRACSignal *viewControllerSignal = [authenticatedSignal map:^(NSNumber *isAuthenticated) { if (isAuthenticated.boolValue) return [DashboardViewController new]; } else { return [LoginViewController new]; } }];
![Page 16: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/16.jpg)
Select the Right View Controller
YES NO YES
Dashboard Login Dash
board
map { // BOOL to ViewController }
![Page 17: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/17.jpg)
Displaying it on Screen
How do we get the value out?We have to subscribe, like a callback.
- (void)viewDidLoad { [super viewDidLoad];
// Whenever we get a new view controller, PUSH IT [[viewControllerSignal deliverOnMainThread] subscribeNext:^(UIViewController *viewController) { [self showViewController:viewController sender:self]; }];}
![Page 18: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/18.jpg)
Ok, maybe that’s pushing it
Let’s make a custom view controller container!
![Page 19: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/19.jpg)
Switching to the latest view controller
@interface SwitchingController : UIViewController
- (instancetype)initWithViewControllers:(RACSignal *)viewControllers;
@property (nonatomic, readonly) UIViewController *currentViewController;
@end
Manages a signal of view controllers, always displaying the most recent one
![Page 20: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/20.jpg)
- (void)viewDidLoad { [super viewDidLoad];
[[self.viewControllers deliverOnMainThread] subscribeNext:^(UIViewController *viewController) { [self transitionFrom:self.currentViewController to:viewController]; }];}
Setting Up
When the view loads, subscribe to our signal
![Page 21: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/21.jpg)
- (void)transitionFrom:(UIViewController *)fromViewController to:(UIViewController *)toViewController { if (!fromViewController) { [self addInitialViewController:toViewController]; return; }
[self addChildViewController:nextViewController]; nextViewController.view.frame = self.view.bounds; [self.view addSubview:nextViewController.view]; [previousViewController willMoveToParentViewController:nil];
[self transitionFromViewController:fromViewController toViewController:toViewController duration:0.5 options:UIViewAnimationOptionTransitionCrossDissolve animations:nil completion:^(BOOL finished) { [toViewController didMoveToParentViewController:self]; [fromViewController removeFromParentViewController]; self.currentViewController = toViewController; }];}
Transitioning
![Page 22: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/22.jpg)
YES NO YES
DashboardLogin
![Page 23: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/23.jpg)
Finishing Up
What happens if the view controller changes rapidly?
![Page 24: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/24.jpg)
- (void)viewDidLoad { [super viewDidLoad];
[[[self.viewControllers throttle:0.5] deliverOnMainThread] subscribeNext:^(UIViewController *viewController) { [self transitionFrom:self.currentViewController to:viewController]; }];}
Simple Throttling
Only take a new view controller if 0.5 seconds have passed.
![Page 25: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/25.jpg)
v2: Only throttle while animating
Keep track of when we’re animating
- (void)transitionFrom:(UIViewController *)fromViewController to:(UIViewController *)toViewController { // code self.animating = YES;
[self transitionFromViewController:fromViewController toViewController:toViewController duration:0.5 options:UIViewAnimationOptionTransitionCrossDissolve animations:nil completion:^(BOOL finished) { // more code self.animating = NO; }];}
![Page 26: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/26.jpg)
v2: Only throttle while animating
Throttle only if we are animating
[[[self.viewControllers throttle:0.5 valuesPassingTest:^(id _) { return self.isAnimating; }] deliverOnMainThread] subscribeNext:^(UIViewController *viewController) { [self transitionFrom:self.currentViewController to:viewController]; }];
![Page 27: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/27.jpg)
What have we learned?
• Signals can represent real world events (Logging in/out)
• We can transform them using operators like map
• We can control timing through operators like throttle
![Page 28: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/28.jpg)
1. Reactive View Controller
2. Reactive Notifications
3. Functional Data Processing
![Page 29: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/29.jpg)
Hot Signals
• Events happen regardless of any observers.
• Stream of *events* happening in the world.
• e.g. UI interaction, notifications
![Page 30: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/30.jpg)
Cold Signals
• Subscribing starts the stream of events.
• Stream of results caused by some side effects.
• e.g. network calls, database transactions
![Page 31: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/31.jpg)
Push Notifications
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo { // Do something horrible™ in here}
![Page 32: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/32.jpg)
A Better Option
typedef NS_ENUM(NSUInteger, NotificationType) { NotificationTypeA, NotificationTypeB, NotificationTypeC,};
@protocol NotificationProvider
- (RACSignal *)notificationSignalForNotificationType: (NotificationType)type;
@end
![Page 33: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/33.jpg)
We Want This:
@property id<NotificationProvider> notificationProvider;
- (void)viewDidLoad { [[[self.notificationProvider notificationSignalForNotificationType:NotificationTypeA] deliverOnMainThread] subscribeNext:^(Notification *notification) { [self updateInterfaceWithNotification:notification]; }] }
![Page 34: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/34.jpg)
A New Friend!
Lift a selector into the reactive world
- (RACSignal *)rac_signalForSelector:(SEL)selector;
The returned signal will fire an event every time the method is called.
![Page 35: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/35.jpg)
Let’s Do It!
- (RACSignal *)notificationSignalForNotificationType: (NotificationType)type { return [[[self rac_signalForSelector:@selector(application:didReceiveRemoteNotification:)] map:^(RACTuple *arguments) { return arguments.second; }] map:^(NSDictionary *userInfo) { // Parse our user info dictionary into a model object return [self parseNotification:userInfo]; }] filter:^(Notification *notification) notification.type = type; }];}
![Page 36: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/36.jpg)
NSDict NSDict NSDict
NotificationA
NotificationB
NotificationA
map { [self parseNotification:userInfo]; }
filter { notification.type == typeA }
NotificationA
NotificationA
![Page 37: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/37.jpg)
A Wild Local Notification Appears!
• We don't want to duplicate our current notification handling.
• Local and remote notifications should have the same effects.
![Page 38: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/38.jpg)
RACSignal *remoteNotificationInfo = [[self rac_signalForSelector:@selector(application:didReceiveRemoteNotification:)] map:^(RACTuple *arguments) { return arguments.second }];
RACSignal *localNotificationInfo = [[self rac_signalForSelector:@selector(application:didReceiveLocalNotification:)] map:^(RACTuple *arguments) { UILocalNotification *notification = arguments.second; return notification.userInfo; }];
return [[[remoteNotificationInfo merge:localNotificationInfo] map:^(NSDictionary *userInfo) { // Parse our user info dictionary into a model object return [self parseNotification:userInfo]; }]
filter:^(Notification *notification) { return notification.type == type;}];
![Page 39: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/39.jpg)
Problem
• We only get notifications sent *after* we subscribe.
• We can't easily update app state or UI that is created afterthe notification is sent.
![Page 40: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/40.jpg)
Solution?
[signal replayLast]
Whenever you subscribe to the signal, it will immediately send you the most recent value from the stream.
![Page 41: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/41.jpg)
Replay it
return [[[remoteNotificationInfo merge:localNotificationInfo] map:^(NSDictionary *userInfo) { // Parse our user info dictionary into a model object return [self parseNotification:userInfo]; }] filter:^(Notification *notification) { return notification.type == type; }] replayLast];
return [[remoteNotificationInfo merge:localNotificationInfo] map:^(NSDictionary *userInfo) { // Parse our user info dictionary into a model object return [self parseNotification:userInfo]; }] filter:^(Notification *notification) { return notification.type == type; }];
![Page 42: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/42.jpg)
What have we learned?
• Signals can model complex app behaviour like notifications
• We can combine signals in interesting ways
• Helpers like signalForSelector allow us to lift regular functions into signals
![Page 43: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/43.jpg)
1. Reactive View Controller
2. Reactive Notifications
3. Functional Data Processing
![Page 44: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/44.jpg)
Describing an Algorithm with FunctionsExample: Finding the best voucher to cover a
purchase
• If there are any vouchers with higher value than the purchase, use the lowest valued of those
• Otherwise, use the highest valued voucher available
![Page 45: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/45.jpg)
Imperative Approach
![Page 46: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/46.jpg)
NSArray *sortedVouchers = [vouchers sortedArrayUsingComparator:^NSComparisonResult(id<Voucher> voucher1, id<Voucher> voucher2) { return [voucher1 compare:voucher2];}];
NSArray *vouchers = [[self voucherLibrary] vouchers];
id<Voucher> bestVoucher = nil; for (id<Voucher> voucher in sortedVouchers) { NSDecimalNumber *voucherAmount = voucher.amount; if (!voucherAmount) continue;
if ([voucherAmount isLessThan:purchaseAmount]) { bestVoucher = voucher; } else if ([voucherAmount isGreaterThanOrEqualTo:purchaseAmount]) { bestVoucher = voucher; break; } }
return bestVoucher;}
![Page 47: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/47.jpg)
NSMutableArray *vouchersWithValue = [NSMutableArray array];for (id<Voucher> voucher in sortedVouchers) { if (voucher.amount) { [vouchersWithValue addObject:voucher]; }}
id<Voucher> bestVoucher = nil;for (id<Voucher> voucher in vouchersWithValue) { NSDecimalNumber *voucherAmount = voucher.amount; if ([voucherAmount isLessThen:purchaseAmount]) { bestVoucher = voucher; } else if ([voucherAmount isGreaterThanOrEqualTo:purchaseAmount]) { bestVoucher = voucher; break; }}
Separate the Filter?
![Page 48: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/48.jpg)
Functional Approach
![Page 49: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/49.jpg)
- (id<Voucher>)voucherForPurchaseAmount:(NSDecimalNumber *)purchaseAmount { [[[[[[[[self voucherLibrary] vouchers] sortedArrayUsingComparator:^NSComparisonResult(id<Voucher> voucher1, id<Voucher> voucher2) { return [voucher1 compare:voucher2]; }] rac_sequence] filter:^BOOL(id<Voucher> voucher) { return voucher.amount != nil; }] yow_takeUptoBlock:^BOOL(id<Voucher> voucher) { return [voucher.amount isGreaterThanOrEqualTo:purchaseAmount]; }] array] lastObject];}
![Page 50: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/50.jpg)
NSArray *sortedVouchers = [vouchers sortedArrayUsingComparator:^NSComparisonResult(id<Voucher> voucher1, id<Voucher> voucher2) { return [voucher1 compare:voucher2];}];
NSArray *vouchers = [[self voucherLibrary] vouchers];
id<Voucher> bestVoucher = nil; for (id<Voucher> voucher in sortedVouchers) { NSDecimalNumber *voucherAmount = voucher.amount; if (!voucherAmount) continue;
if ([voucherAmount isLessThan:purchaseAmount]) { bestVoucher = voucher; } else if ([voucherAmount isGreaterThanOrEqualTo:purchaseAmount]) { bestVoucher = voucher; break; } }
return bestVoucher;}
![Page 51: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/51.jpg)
What have we learned?
• Functional code can be more readable
• It's easy to convert between imperative and functional code using ReactiveCocoa
• Signals are lazy
![Page 52: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/52.jpg)
1. Reactive View Controller
2. Reactive Notifications
3. Functional Data Processing
![Page 53: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/53.jpg)
Resources
• reactivecocoa.io
• ReactiveCocoa on GitHub
• ReactiveCocoa - The Definitive Introduction (Ray Wenderlich)
• A First Look at ReactiveCocoa 3.0 (Scott Logic)
![Page 54: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/54.jpg)
Next Steps
• Try it out!
• Don’t be scared to go all in
![Page 55: ReactiveCocoa in Practice · Why ReactiveCocoa? “Instead of telling a computer how to do it’s job, why don’t we just tell it what it’s job is, and let it figure the rest out.”](https://reader033.vdocuments.us/reader033/viewer/2022042005/5e6fac9f0d2e1f58113290e1/html5/thumbnails/55.jpg)
Thanks!Questions?