SlideShare a Scribd company logo
REACTIVECOCOA GOODNESS
PART I OF II
3PHASES OF LEARNING REACTIVECOCOA
1
ReactiveCocoa Goodness - Part I of II
2
ReactiveCocoa Goodness - Part I of II
3
ReactiveCocoa Goodness - Part I of II
WHAT IS REACTIVECOCOA?
AUTHORS (GITHUB FOLKS) SAY:
ReactiveCocoa (RAC) is an Objective-C framework inspired by Functional
Reactive Programming. It provides APIs for composing and transforming
streams of values.
THE IDEA TO CREATE REACTIVECOCOA SEEMS
TO HAVE COME FROM RX (MICROSOFT .NET),
WHICH IS SIMILAR.
RAC ALLOWS US AN EVENT-BASED
PROGRAMMING MODEL WHICH MAKES STATE
TRACKING OBSOLETE - in theory.
ONE THING IS CERTAIN:
IT MAKES STATE EASIER TO MAINTAIN.
SOME PEOPLE THINK RAC IS ALL ABOUT THIS...
// Keeps someObject.property synced with
// otherObject.other.property
// -> one-way binding
RAC(someObject, property) =
RACObserve(otherObject, other.property);
...OR THIS...
// Keeps someObject.property synced with
// otherObject.other.property
// and vice versa -> two-way binding
RACChannelTo(someObject, property) =
RACChannelTo(otherObject, other.property);
... BUT RAC IS SO MUCH MORE!
RAC = SIGNALS + SUBSCRIBERS
A SIGNAL IS A STREAM OF VALUES.
SIGNALS CAN BE TRANSFORMED, COMBINED, ETC.
A SUBSCRIBER SUBSCRIBES TO A SIGNAL.
RAC LETS BLOCKS, OBJECTS, AND PROPERTIES SUBSCRIBE TO SIGNALS.
USING SIGNALS AND SUBSCRIBERS, YOU CAN
MODEL ANY REACTION TO ANY EVENT THAT
HAPPENS IN YOUR APPLICATION.
MOST OF UI-CENTERED CODE
ACTUALLY REACTS TO SOMETHING!
DIVING INTO SIGNALS
MOST TRIVIAL SIGNAL:
RACEmptySignal
// Sends no value. Ever. #yolo
RACSignal *sendNothing =
[RACEmptySignal empty];
MOST TRIVIAL SIGNAL THAT SENDS VALUES:
RACReturnSignal
// All subscribers will immediately receive an
// empty array as 'next' value on subscription.
RACSignal *returnEmptyArrayOnSubscription =
[RACReturnSignal return:@[]];
BRIDGE OOP/FRP WORLD:
RACSubject
- (id)init {
if (self = [super init]) {
self.loadMoreSubject = [RACSubject subject];
}
return self;
}
- (void)loadMore {
[self.loadMoreSubject sendNext:nil];
}
OTHER SIGNALS:
RACSignal (DUH!),
RACReplaySubject,
RACChannelTerminal,
RACErrorSignal,...
UIKIT BATTERIES INCLUDED:
UITextfield.rac_textSignal
NSObject.rac_willDeallocSignal
UITableviewCell.rac_prepareForReuseSignal
UIButton.rac_command
UIRefreshControl.rac_command
...
SIGNAL LIBRARIES ON COCOAPODS
pod search RACExtensions
pod search reactivecocoa
YOU BUILD APP LOGIC BY
TRANSFORMING VALUES SENT
BY SIGNALS
MAP
[usersSignal map:^NSString *(MMUser *user) {
return user.email;
}];
FILTER
[usersSignal filter:^BOOL(MMUser *user) {
return user.isEnabled;
}];
ZIP
// If signalOne and signalTwo have both
// sent a value, signalOne's value is passed on.
[RACSignal zip:@[signalOne, signalTwo]
reduce:^id(RACTuple *t) {
return t.first;
}];
MERGE SIGNALS
// No matter if the user or a notification
// provokes a value send, the value is passed
// on in both cases.
[RACSignal merge:@[userTriggerSignal,
notificationCenterTriggerSignal]]
FLATTEN OR MAP/FLATTEN SIGNALS
// First maps all freshly sent requestParams to a new
// signal that will eventually send a server response.
// Then applies flatten such that we get all those
// server responses directly as values.
RACSignal *currentUsers = [requestParamsSignal
flattenMap:^RACStream *(NSDictionary *requestParams) {
return [MMAPI.sharedInstance
allUsersWithParams:requestParams];
}
];
(YEAH, YOU CAN BUILD
SIGNALS OF SIGNALS OF
SIGNALS.)
ReactiveCocoa Goodness - Part I of II
CONCAT SIGNALS
// Catches any error in signal, waits 1 second,
// then passes on the error, and then immediately
// retries (= resubscribes). Forever.
[[signal catch:^(NSError *error) {
return [[[RACSignal
empty]
delay:1.0]
concat:[RACSignal error:error]];
}] retry];
SCAN/REDUCE
// Starts off with a mutable array, and adds all
// events that are ever sent by the 'events' signal.
// E.g. for infinite scrolling.
RACSignal *combinedEventsInAllPages = [events
scanWithStart:NSMutableArray.new
reduce:^id(NSMutableArray *running,
NSArray *eventsInPage) {
[running addObject:eventsInPage];
return running;
}];
SKIP VALUES
// RACObserve immediately sends the current
// property value. Skip:1 'swallows' that one.
[[RACObserve(self, someProperty)] skip: 1];
TAKE X VALUES AND STOP
// Only sends the first 3 text values.
// Then the signal is disposed of.
[textField.rac_textSignal take: 3];
DISTINCT UNTIL CHANGED
// Does only send distinct (= first and new) values.
[RACObserve(self, isUserLoggedIn) distinctUntilChanged];
THROTTLE/DELAY/REPEAT...
... THERE IS A TRANSFORM FOR EVERYTHING.
SIGNALS CAN SWITCH THREADS
RAC(self, results) = [[[[RACReturnSignal
return:@[@(M_PI), @(M_E), @(M_SQRT1_2)]]
deliverOn:RACScheduler.scheduler]
// All that follows happens on a background thread
map:^NSNumber *(NSNumber *specialNumber) {
// Do expensive calculations
// NSNumber *result = ...
return result;
}]
// All that follows (RAC assignment) happens
// on the main thread
deliverOn:RACScheduler.mainThreadScheduler];
RACCOMMAND = ONE-OFF SIGNAL WRAPPER
self.registerCommand = [[RACCommand alloc] initWithEnabled:
[self.emailField.rac_textSignal map:^id(NSString *text) {
return @(text.length > 0);
}]
signalBlock:^RACSignal *(NSDictionary *params) {
return [MMAPI.sharedInstance registerWithParams:params];
}];
[self.registerCommand.executionSignals.flatten subscribeNext:^(id result) {
NSLog(@"Successfully registered!");
}];
// ...
[self.registerCommand execute:@{MMAPIRegisterEmail: self.emailField.text,
MMAPIRegisterPassword: self.pwField.text}];
SIGNALS CAN BE HOT OR COLD
A hot signal is a signal that sends values (and
presumably does work) regardless of whether it
has any subscribers.
A cold signal is a signal that defers its work and
the sending of any values until it has a
subscriber.
Hot signals often don't send subscribers all
values of all time, but only values after their
subscription time.
SO WE HAVE SIGNALS.
NOW WE NEED TO SUBSCRIBE.
SUBSCRIBE WITH A BLOCK
// Prints current date & time every second
RACSignal *dates = [RACSignal interval:1.0
onScheduler:RACScheduler.mainThreadScheduler];
[dates subscribeNext:^(NSDate *date) {
NSLog([NSDateFormatter
localizedStringFromDate:[NSDate date]
dateStyle:NSDateFormatterShortStyle
timeStyle:NSDateFormatterFullStyle]);
}];
SUBSCRIBE WITH A PROPERTY (KEYPATH)
// RAC() is a clever macro that abuses
// subscripting to let subscription look
// like a left-hand assignment
RAC(self.proxyObject.awesomeArray) =
[RACReturnSignal return:@[]];
INJECT BLOCK-BASED SIDE-EFFECTS
// doNext: is 'woven' into the signal chain,
// the side-effect becomes part of the signal.
// Dangerous, but sometimes necessary!
parametersOnRefreshOrParameterChanged =
[parametersOnRefreshOrParameterChanged
doNext:^(NSDictionary *parameters) {
@strongify(self)
self.isRefreshing = YES;
}];
SUBSCRIBE WITH A METHOD
// Calls updateAuthorizationWithAuthToken: when
// RACObserve() sends a value. RACObserve()
// will btw immediately send the first value,
// synchronously.
[self rac_liftSelector:
@selector(updateAuthorizationWithAuthToken:)
withSignals: RACObserve(MMSession.sharedSession,
currentCredentials.authToken), nil];
WHAT RAC BUYS YOU
CAN BIND UI COMPONENT VALUES TO MODEL
VALUES, INCLUDING TRANSFORMATIONS ...
... WHICH LEADS TO:
A REAL MVVM PARADIGM
CAN CALL METHODS WITH MULTIPLE
PARAMETERS WHEN SIGNALS FIRE IN A
CERTAIN CONFIGURATION
ELIMINATES THOSE ERROR-PRONE BOOL
FLAGS YOU USE TO KEEP TRACK OF COMPLEX
STATE
CAN WAIT FOR MULTIPLE SIGNALS UNTIL IT
DOES SOMETHING
(TEDIOUS AND DANGEROUS TO DO WITH
BOOL FLAGS)
MAKES THREAD SWITCHES EASY AS !
FORCES YOU TO THINK TWICE BEFORE
INTRODUCING A SIDE-EFFECT.
ENCOURAGES IMMUTABLE OBJECTS
(BUT DOES NOT ENFORCE THEM).
MAKES CODE EVEN MORE REUSABLE
(E.G.NETWORK RESPONSE ERROR FILTER)
NICE INTERFACE TO KVO AND
NSNotificationCenter
HAS NICE COLLECTION UTILS INDEPENDENT
OF SIGNALS
(MIGHT GET REMOVED SOMEDAY):
RACSequence
LIMITATIONS & PITFALLS
BLOCKS CAN EASILY CREATE RETAIN CYCLES
☞ ALWAYS USE @WEAKIFY AND @STRONGIFY
IF YOU OVERDO IT, PERFORMANCE SUFFERS
☞ WATCH BINDINGS IN UITABLEVIEWCELLS!
NO WAY FOR DISTINCTUNTILCHANGED TO
NOT USE ISEQUAL !
NO SPECIAL TREATMENT FOR MUTABLE
ARRAYS
[[[[[[[[CODE BECOMES] HARD] TO]
UNDERSTAND] IF YOU] NEST] SIGNALS]
TOO MUCH]
☞ USE INTERMEDIATE PROPERTIES!
HOW DOES RAC
DO ALL THIS?
BLOCKS, KVO,
METHOD SWIZZLING,
MACROS, GCD, LOCKS,...
(maybe every runtime feature there is)
MEMORY MANAGEMENT just works™.
BUT IT'S EASY TO CREATE SIGNALS THAT
LIVE FOREVER!
RAC'S CODE IS REALLY ADVANCED STUFF,
BUT HAVING A LOOK AT IT IS WORTH IT.
A WORD ABOUT SWIFT:
RAC can be used with Swift (didn't test it yet),
but a pure Swift implementation will take a while.
Also, KVO will not work without NSObject anyway.
Proof of concept is currently being merged into RAC:
https://github.com/jspahrsummers/RxSwift
IF YOU WANT TO LEARN RAC:
1. First have a look at how subscriptions work
2. Read through RAC's Github issues (mostly RAC Q/A)
3. Start slow, create a lot of intermediate properties
4. Go wild!
IF YOU ARE STUCK,
PING ME AT
@MANUELMALY
NO REALLY. DO IT!
THANKS FOR LISTENING!
COMING SOON: PART II INCLUDING
MVVM PATTERN AND MORE CODE
@MANUELMALY
CREATIVEPRAGMATICS.COM

More Related Content

PDF
Learn You a ReactiveCocoa for Great Good
PDF
ReactiveCocoa in Practice
PDF
An Introduction to Reactive Cocoa
PDF
Reactive cocoa made Simple with Swift
PDF
ReactiveCocoa and Swift, Better Together
PDF
Introduction to reactive programming & ReactiveCocoa
PDF
Intro to ReactiveCocoa
PDF
Swift Sequences & Collections
Learn You a ReactiveCocoa for Great Good
ReactiveCocoa in Practice
An Introduction to Reactive Cocoa
Reactive cocoa made Simple with Swift
ReactiveCocoa and Swift, Better Together
Introduction to reactive programming & ReactiveCocoa
Intro to ReactiveCocoa
Swift Sequences & Collections

What's hot (20)

PDF
Introduction to RxJS
PDF
Reactive cocoa
PDF
Map kit light
PDF
Angular and The Case for RxJS
PPTX
PPTX
Reactive Java (33rd Degree)
PPTX
Rxjs ngvikings
PDF
My Gentle Introduction to RxJS
PDF
RxJava on Android
PDF
Cocoa heads 09112017
PDF
Intro to RxJava/RxAndroid - GDG Munich Android
PDF
Reactive Programming for a demanding world: building event-driven and respons...
PDF
Reactive programming with RxJava
PPTX
Avoiding Callback Hell with Async.js
PDF
Angular & RXJS: examples and use cases
PPTX
Luis Atencio on RxJS
PDF
Oop assignment 02
PPTX
Rxjs swetugg
PDF
GKAC 2015 Apr. - RxAndroid
PDF
JavaOne 2013: Java 8 - The Good Parts
Introduction to RxJS
Reactive cocoa
Map kit light
Angular and The Case for RxJS
Reactive Java (33rd Degree)
Rxjs ngvikings
My Gentle Introduction to RxJS
RxJava on Android
Cocoa heads 09112017
Intro to RxJava/RxAndroid - GDG Munich Android
Reactive Programming for a demanding world: building event-driven and respons...
Reactive programming with RxJava
Avoiding Callback Hell with Async.js
Angular & RXJS: examples and use cases
Luis Atencio on RxJS
Oop assignment 02
Rxjs swetugg
GKAC 2015 Apr. - RxAndroid
JavaOne 2013: Java 8 - The Good Parts
Ad

Similar to ReactiveCocoa Goodness - Part I of II (20)

PPT
Lviv MD Day 2015 Павло Захаров "Reactive cocoa: paradigm shift"
PDF
Pieter De Baets - An introduction to React Native
PDF
Talk KVO with rac by Philippe Converset
PDF
Reactive Cocoa
PDF
Functional Reactive Programming (CocoaHeads Bratislava)
PDF
Reactive cocoa
PDF
High Performance Microservices with Ratpack and Spring Boot
PDF
Saving lives with rx java
PPT
Sqlapi0.1
PDF
«ReactiveCocoa и MVVM» — Николай Касьянов, SoftWear
PDF
Structured concurrency with Kotlin Coroutines
PDF
MCE^3 - Ágnes Vásárhelyi - ReactiveCocoa Reloaded
PPT
iOS Multithreading
PDF
Introduction to Redux (for Angular and React devs)
PDF
Functional Reactive Programming dengan ReactiveCocoa
PPTX
Getting Reactive with Cycle.js and xstream
PDF
Cassandra 2.1 boot camp, Overview
PDF
The Ring programming language version 1.8 book - Part 90 of 202
PDF
Building Scalable Stateless Applications with RxJava
PPTX
Managing State in React Apps with RxJS by James Wright at FrontCon 2019
Lviv MD Day 2015 Павло Захаров "Reactive cocoa: paradigm shift"
Pieter De Baets - An introduction to React Native
Talk KVO with rac by Philippe Converset
Reactive Cocoa
Functional Reactive Programming (CocoaHeads Bratislava)
Reactive cocoa
High Performance Microservices with Ratpack and Spring Boot
Saving lives with rx java
Sqlapi0.1
«ReactiveCocoa и MVVM» — Николай Касьянов, SoftWear
Structured concurrency with Kotlin Coroutines
MCE^3 - Ágnes Vásárhelyi - ReactiveCocoa Reloaded
iOS Multithreading
Introduction to Redux (for Angular and React devs)
Functional Reactive Programming dengan ReactiveCocoa
Getting Reactive with Cycle.js and xstream
Cassandra 2.1 boot camp, Overview
The Ring programming language version 1.8 book - Part 90 of 202
Building Scalable Stateless Applications with RxJava
Managing State in React Apps with RxJS by James Wright at FrontCon 2019
Ad

Recently uploaded (20)

PDF
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
PDF
Understanding Forklifts - TECH EHS Solution
PDF
System and Network Administraation Chapter 3
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 41
PPTX
Transform Your Business with a Software ERP System
PPTX
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
PPTX
Essential Infomation Tech presentation.pptx
PPTX
L1 - Introduction to python Backend.pptx
PPTX
history of c programming in notes for students .pptx
PDF
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
PDF
Digital Strategies for Manufacturing Companies
PDF
Flood Susceptibility Mapping Using Image-Based 2D-CNN Deep Learnin. Overview ...
PDF
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
PDF
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
PDF
PTS Company Brochure 2025 (1).pdf.......
PPTX
CHAPTER 2 - PM Management and IT Context
PDF
Odoo Companies in India – Driving Business Transformation.pdf
PDF
Wondershare Filmora 15 Crack With Activation Key [2025
PPTX
Introduction to Artificial Intelligence
PDF
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
Understanding Forklifts - TECH EHS Solution
System and Network Administraation Chapter 3
Internet Downloader Manager (IDM) Crack 6.42 Build 41
Transform Your Business with a Software ERP System
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
Essential Infomation Tech presentation.pptx
L1 - Introduction to python Backend.pptx
history of c programming in notes for students .pptx
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
Digital Strategies for Manufacturing Companies
Flood Susceptibility Mapping Using Image-Based 2D-CNN Deep Learnin. Overview ...
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
PTS Company Brochure 2025 (1).pdf.......
CHAPTER 2 - PM Management and IT Context
Odoo Companies in India – Driving Business Transformation.pdf
Wondershare Filmora 15 Crack With Activation Key [2025
Introduction to Artificial Intelligence
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free

ReactiveCocoa Goodness - Part I of II

  • 2. 3PHASES OF LEARNING REACTIVECOCOA
  • 3. 1
  • 5. 2
  • 7. 3
  • 10. AUTHORS (GITHUB FOLKS) SAY: ReactiveCocoa (RAC) is an Objective-C framework inspired by Functional Reactive Programming. It provides APIs for composing and transforming streams of values.
  • 11. THE IDEA TO CREATE REACTIVECOCOA SEEMS TO HAVE COME FROM RX (MICROSOFT .NET), WHICH IS SIMILAR.
  • 12. RAC ALLOWS US AN EVENT-BASED PROGRAMMING MODEL WHICH MAKES STATE TRACKING OBSOLETE - in theory.
  • 13. ONE THING IS CERTAIN: IT MAKES STATE EASIER TO MAINTAIN.
  • 14. SOME PEOPLE THINK RAC IS ALL ABOUT THIS... // Keeps someObject.property synced with // otherObject.other.property // -> one-way binding RAC(someObject, property) = RACObserve(otherObject, other.property);
  • 15. ...OR THIS... // Keeps someObject.property synced with // otherObject.other.property // and vice versa -> two-way binding RACChannelTo(someObject, property) = RACChannelTo(otherObject, other.property);
  • 16. ... BUT RAC IS SO MUCH MORE!
  • 17. RAC = SIGNALS + SUBSCRIBERS
  • 18. A SIGNAL IS A STREAM OF VALUES. SIGNALS CAN BE TRANSFORMED, COMBINED, ETC.
  • 19. A SUBSCRIBER SUBSCRIBES TO A SIGNAL. RAC LETS BLOCKS, OBJECTS, AND PROPERTIES SUBSCRIBE TO SIGNALS.
  • 20. USING SIGNALS AND SUBSCRIBERS, YOU CAN MODEL ANY REACTION TO ANY EVENT THAT HAPPENS IN YOUR APPLICATION.
  • 21. MOST OF UI-CENTERED CODE ACTUALLY REACTS TO SOMETHING!
  • 23. MOST TRIVIAL SIGNAL: RACEmptySignal // Sends no value. Ever. #yolo RACSignal *sendNothing = [RACEmptySignal empty];
  • 24. MOST TRIVIAL SIGNAL THAT SENDS VALUES: RACReturnSignal // All subscribers will immediately receive an // empty array as 'next' value on subscription. RACSignal *returnEmptyArrayOnSubscription = [RACReturnSignal return:@[]];
  • 25. BRIDGE OOP/FRP WORLD: RACSubject - (id)init { if (self = [super init]) { self.loadMoreSubject = [RACSubject subject]; } return self; } - (void)loadMore { [self.loadMoreSubject sendNext:nil]; }
  • 28. SIGNAL LIBRARIES ON COCOAPODS pod search RACExtensions pod search reactivecocoa
  • 29. YOU BUILD APP LOGIC BY TRANSFORMING VALUES SENT BY SIGNALS
  • 30. MAP [usersSignal map:^NSString *(MMUser *user) { return user.email; }];
  • 31. FILTER [usersSignal filter:^BOOL(MMUser *user) { return user.isEnabled; }];
  • 32. ZIP // If signalOne and signalTwo have both // sent a value, signalOne's value is passed on. [RACSignal zip:@[signalOne, signalTwo] reduce:^id(RACTuple *t) { return t.first; }];
  • 33. MERGE SIGNALS // No matter if the user or a notification // provokes a value send, the value is passed // on in both cases. [RACSignal merge:@[userTriggerSignal, notificationCenterTriggerSignal]]
  • 34. FLATTEN OR MAP/FLATTEN SIGNALS // First maps all freshly sent requestParams to a new // signal that will eventually send a server response. // Then applies flatten such that we get all those // server responses directly as values. RACSignal *currentUsers = [requestParamsSignal flattenMap:^RACStream *(NSDictionary *requestParams) { return [MMAPI.sharedInstance allUsersWithParams:requestParams]; } ];
  • 35. (YEAH, YOU CAN BUILD SIGNALS OF SIGNALS OF SIGNALS.)
  • 37. CONCAT SIGNALS // Catches any error in signal, waits 1 second, // then passes on the error, and then immediately // retries (= resubscribes). Forever. [[signal catch:^(NSError *error) { return [[[RACSignal empty] delay:1.0] concat:[RACSignal error:error]]; }] retry];
  • 38. SCAN/REDUCE // Starts off with a mutable array, and adds all // events that are ever sent by the 'events' signal. // E.g. for infinite scrolling. RACSignal *combinedEventsInAllPages = [events scanWithStart:NSMutableArray.new reduce:^id(NSMutableArray *running, NSArray *eventsInPage) { [running addObject:eventsInPage]; return running; }];
  • 39. SKIP VALUES // RACObserve immediately sends the current // property value. Skip:1 'swallows' that one. [[RACObserve(self, someProperty)] skip: 1];
  • 40. TAKE X VALUES AND STOP // Only sends the first 3 text values. // Then the signal is disposed of. [textField.rac_textSignal take: 3];
  • 41. DISTINCT UNTIL CHANGED // Does only send distinct (= first and new) values. [RACObserve(self, isUserLoggedIn) distinctUntilChanged];
  • 42. THROTTLE/DELAY/REPEAT... ... THERE IS A TRANSFORM FOR EVERYTHING.
  • 43. SIGNALS CAN SWITCH THREADS RAC(self, results) = [[[[RACReturnSignal return:@[@(M_PI), @(M_E), @(M_SQRT1_2)]] deliverOn:RACScheduler.scheduler] // All that follows happens on a background thread map:^NSNumber *(NSNumber *specialNumber) { // Do expensive calculations // NSNumber *result = ... return result; }] // All that follows (RAC assignment) happens // on the main thread deliverOn:RACScheduler.mainThreadScheduler];
  • 44. RACCOMMAND = ONE-OFF SIGNAL WRAPPER self.registerCommand = [[RACCommand alloc] initWithEnabled: [self.emailField.rac_textSignal map:^id(NSString *text) { return @(text.length > 0); }] signalBlock:^RACSignal *(NSDictionary *params) { return [MMAPI.sharedInstance registerWithParams:params]; }]; [self.registerCommand.executionSignals.flatten subscribeNext:^(id result) { NSLog(@"Successfully registered!"); }]; // ... [self.registerCommand execute:@{MMAPIRegisterEmail: self.emailField.text, MMAPIRegisterPassword: self.pwField.text}];
  • 45. SIGNALS CAN BE HOT OR COLD A hot signal is a signal that sends values (and presumably does work) regardless of whether it has any subscribers. A cold signal is a signal that defers its work and the sending of any values until it has a subscriber. Hot signals often don't send subscribers all values of all time, but only values after their subscription time.
  • 46. SO WE HAVE SIGNALS. NOW WE NEED TO SUBSCRIBE.
  • 47. SUBSCRIBE WITH A BLOCK // Prints current date & time every second RACSignal *dates = [RACSignal interval:1.0 onScheduler:RACScheduler.mainThreadScheduler]; [dates subscribeNext:^(NSDate *date) { NSLog([NSDateFormatter localizedStringFromDate:[NSDate date] dateStyle:NSDateFormatterShortStyle timeStyle:NSDateFormatterFullStyle]); }];
  • 48. SUBSCRIBE WITH A PROPERTY (KEYPATH) // RAC() is a clever macro that abuses // subscripting to let subscription look // like a left-hand assignment RAC(self.proxyObject.awesomeArray) = [RACReturnSignal return:@[]];
  • 49. INJECT BLOCK-BASED SIDE-EFFECTS // doNext: is 'woven' into the signal chain, // the side-effect becomes part of the signal. // Dangerous, but sometimes necessary! parametersOnRefreshOrParameterChanged = [parametersOnRefreshOrParameterChanged doNext:^(NSDictionary *parameters) { @strongify(self) self.isRefreshing = YES; }];
  • 50. SUBSCRIBE WITH A METHOD // Calls updateAuthorizationWithAuthToken: when // RACObserve() sends a value. RACObserve() // will btw immediately send the first value, // synchronously. [self rac_liftSelector: @selector(updateAuthorizationWithAuthToken:) withSignals: RACObserve(MMSession.sharedSession, currentCredentials.authToken), nil];
  • 52. CAN BIND UI COMPONENT VALUES TO MODEL VALUES, INCLUDING TRANSFORMATIONS ...
  • 53. ... WHICH LEADS TO: A REAL MVVM PARADIGM
  • 54. CAN CALL METHODS WITH MULTIPLE PARAMETERS WHEN SIGNALS FIRE IN A CERTAIN CONFIGURATION
  • 55. ELIMINATES THOSE ERROR-PRONE BOOL FLAGS YOU USE TO KEEP TRACK OF COMPLEX STATE
  • 56. CAN WAIT FOR MULTIPLE SIGNALS UNTIL IT DOES SOMETHING (TEDIOUS AND DANGEROUS TO DO WITH BOOL FLAGS)
  • 58. FORCES YOU TO THINK TWICE BEFORE INTRODUCING A SIDE-EFFECT.
  • 59. ENCOURAGES IMMUTABLE OBJECTS (BUT DOES NOT ENFORCE THEM).
  • 60. MAKES CODE EVEN MORE REUSABLE (E.G.NETWORK RESPONSE ERROR FILTER)
  • 61. NICE INTERFACE TO KVO AND NSNotificationCenter
  • 62. HAS NICE COLLECTION UTILS INDEPENDENT OF SIGNALS (MIGHT GET REMOVED SOMEDAY): RACSequence
  • 64. BLOCKS CAN EASILY CREATE RETAIN CYCLES ☞ ALWAYS USE @WEAKIFY AND @STRONGIFY
  • 65. IF YOU OVERDO IT, PERFORMANCE SUFFERS ☞ WATCH BINDINGS IN UITABLEVIEWCELLS!
  • 66. NO WAY FOR DISTINCTUNTILCHANGED TO NOT USE ISEQUAL !
  • 67. NO SPECIAL TREATMENT FOR MUTABLE ARRAYS
  • 68. [[[[[[[[CODE BECOMES] HARD] TO] UNDERSTAND] IF YOU] NEST] SIGNALS] TOO MUCH] ☞ USE INTERMEDIATE PROPERTIES!
  • 69. HOW DOES RAC DO ALL THIS?
  • 70. BLOCKS, KVO, METHOD SWIZZLING, MACROS, GCD, LOCKS,... (maybe every runtime feature there is)
  • 71. MEMORY MANAGEMENT just works™. BUT IT'S EASY TO CREATE SIGNALS THAT LIVE FOREVER!
  • 72. RAC'S CODE IS REALLY ADVANCED STUFF, BUT HAVING A LOOK AT IT IS WORTH IT.
  • 73. A WORD ABOUT SWIFT: RAC can be used with Swift (didn't test it yet), but a pure Swift implementation will take a while. Also, KVO will not work without NSObject anyway. Proof of concept is currently being merged into RAC: https://github.com/jspahrsummers/RxSwift
  • 74. IF YOU WANT TO LEARN RAC: 1. First have a look at how subscriptions work 2. Read through RAC's Github issues (mostly RAC Q/A) 3. Start slow, create a lot of intermediate properties 4. Go wild!
  • 75. IF YOU ARE STUCK, PING ME AT @MANUELMALY NO REALLY. DO IT!
  • 76. THANKS FOR LISTENING! COMING SOON: PART II INCLUDING MVVM PATTERN AND MORE CODE