SlideShare a Scribd company logo
1 of 18
Download to read offline
FRPs ReactiveCocoa
FUNCTIONAL
• stateless; state is derived instead

(cell c = cell a + cell b)
• immmmmmmmutable data
• dôraz na high-order funkcie (ktoré produkujú vyýstup na
základe vstupov)
• funkcie ako 1st class objekty
Immutable
Stateless
(Gotcha *) ignorujúc minulosť
REACTIVE
• práca s asynchrónnymi data streams
• …taktiež s nested callbacks, complexnými list filtering/
transformáciami alebo timing concerns
• integruje koncept času a kompozíciu udalostí spolu s
funkcionálnym programovaním.
• od MS, spolu aj s MVVM
ReactiveCocoa
• obj-c / swift implementácia pre iOS & Mac OS X
• zjednocuje programovacie API pre všetky eventy
• KVO, delegate, notifications, block syntax, target-action
• od 3.0 podpora Swift
BUILDING BLOCKS
RACSequence RACSignal
Stream
• push-driven stream• pull-driven stream
• oba zdieľajú viacero spoločných operátorov
RACSequence
• lazily-loaded kolekcie
• podobný účel ako NSArray
• pridáva funkcie, ktoré Foundatin nemá: map*, filter, fold/reduce…
• objekty kolekcie netransformujú, až kým nie sú vytiahnuté (for-in, etc.)
RACSequence *normalizedLongWords = [[words.rac_sequence
filter:^ BOOL (NSString *word) {
return [word length] >= 10;
}]
map:^(NSString *word) {
return [word lowercaseString];
}];
* swift už map vie
RACSignal
• rúra, ktora nesie hodnotu ( input > transform > output )
• signály môžu byť (a budú) reťazené (funkcia pojme
funkciu)
• Chaining of Dependent Operations
• Parallelizing Independent Work
• (Hint *) Signály sú interne postavené na KVO
RACSignal (cont.)
• signál posiela 3 druhy eventov: next, finished, error
• next nesie naše dáta ( = čokoľvek)
• Subscribe (na základe čoho robíme side-effects)
• binding pomocou RAC()
• nahradzujú @property (niekedy)
• neprepisuje/nemodifikuje pôvodný stream. (immutability)
• 0, 1, alebo > 1 subscriberov
• alebo si ich vytvoríme: RACObserve() (zabalí
dynamickú property)
RACSignal	
  *formValid	
  =	
  [RACSignal	
  
	
  	
  	
  	
  combineLatest:@[	
  
self.username.rac_textSignal,	
  
self.emailField.rac_textSignal,	
  
self.passwordField.rac_textSignal,	
  
self.passwordVerificationField.rac_textSignal	
  
]	
  
reduce:^(NSString	
  *username,	
  NSString	
  *email,	
  NSString	
  *password,	
  NSString	
  
*passwordVerification)	
  {	
  
	
  	
  	
  	
  return	
  @([username	
  length]	
  >	
  0	
  &&	
  [email	
  length]	
  >	
  0	
  &&	
  [password	
  length]	
  >	
  
8	
  &&	
  [password	
  isEqual:passwordVerification]);	
  
}];	
  
RAC(self.createButton.enabled)	
  =	
  formValid;
emailField
userNameField
passwordVerifi
cationField
passwordField
combineLatest reduce formValid
NSNumber
(boolean)
NSString
NSString
NSString
NSString
4x NSString
-­‐	
  (RACCommand*)rac_searchCommand	
  
{	
  
	
  	
  	
  	
  if	
  (!_searchCommand)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  @weakify(self)	
  
	
  	
  	
  	
  	
  	
  	
  	
  _searchCommand	
  =	
  [[RACCommand	
  alloc]	
  initWithSignalBlock:^RACSignal	
  *(NSDictionary	
  
*parameters)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  @strongify(self)	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  return	
  [[self.searchHelper	
  rac_searchWithScheduler:[RACScheduler	
  scheduler]	
  
parameters]	
  catch:^RACSignal	
  *(NSError	
  *error)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  DLog(@"Remote	
  Search	
  Error");	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  return	
  [RACSignal	
  return:RACTuplePack(@[])];	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }];	
  
	
  	
  	
  	
  	
  	
  	
  	
  }];	
  
	
  	
  	
  	
  }	
  
	
  	
  	
  	
  return	
  _searchCommand;	
  
}
-­‐	
  (void)viewModelSetup	
  
{	
  
	
  	
  	
  	
  [[[self.rac_searchCommand	
  executionSignals]	
  flatten]	
  	
  
	
   	
  	
  subscribeNext:^(NSArray	
  *	
  array)	
  {	
  	
  	
  	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  [self.data	
  =	
  array];	
  
	
  	
  	
  	
  }];	
  
}
ViewModel
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath:
NSIndexPath) -> UITableViewCell {
...
cell.model = searchVM!.modelForResultAtIndexPath(indexPath)
...
return cell
}
	
  	
  	
  	
  override	
  func	
  viewDidLoad()	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  RACObserve(self.searchVM,	
  "data").ignore(nil).subscribeNext	
  {	
  [unowned	
  self]	
  (any)	
  -­‐>	
  
Void	
  in	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  self.searchResultsTable.reloadData()	
  
	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  }
func searchBarSearchButtonClicked(searchBar: UISearchBar) {
println("search (searchBar.text)")
self.searchVM?.rac_searchCommand.execute(["query" : searchBar.text])
}
ViewController
searchButton.enabled <~ viewModel.rac_searchCommand.executing
-­‐	
  (void)awakeFromNib	
  {	
  
	
  	
  	
  	
  RAC(self.titleLabel,	
  text)	
  =	
  [RACObserve(self,	
  model.title)	
  ignore:nil];	
  
	
  	
  	
  	
  RACSignal	
  *	
  colorSignal	
  =	
  [[RACObserve(self,sectionModel.sectionColorRGBString)	
  
ignore:nil]	
  map:^id(NSString*	
  value)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  return	
  [UIColor	
  colorFromString:value];	
  
	
  	
  	
  	
  }];	
  
	
  	
  	
  	
  RAC(self.resultImage,	
  backgroundColor)	
  =	
  colorSignal;	
  
}
TableViewCell
SWIFT
let usernameTextField: UITextField =
UITextField()
usernameTextField.rac_textSignal()
.mapAs {
(text: NSString) -> NSNumber in
return text.length
}.filterAs {
(number: NSNumber) -> Bool in
return number > 3
}.subscribeNextAs {
(length: NSNumber) in
println(length)
}
OBJ-C
UITextField *usernameTextField =
[[UITextField alloc] init];
[[[usernameTextField.rac_textSignal
map:^(NSString *value) {
return @(value.length);
}]
filter:^BOOL(NSNumber *value) {
return value > 0;
}]
subscribeNext:^(NSNumber *length) {
NSLog(@"%d", [length intValue]);
}];
Fluent API
[[[[[[[[[[[[[[[[I dont] think] fluent] interface] patterns] will] be]
useful] unless] you] want] to] write] methods] like] this];
zip()
map() defer()
catch() reduce()
dinstinctUntilChanged()
deliverOn()
filter()
throttle()
flatten()
merge()
https://github.com/dogwith1eye/
101RACSamples
…
…
?
MOTIVATION
https://github.com/dogwith1eye/101RACSamples
github.com/ColinEberhardt/
github.com/artsy/eidolon
INSPIRATION

More Related Content

Viewers also liked

12. Maros Holly - Sygic
12. Maros Holly - Sygic12. Maros Holly - Sygic
12. Maros Holly - SygicMobCon
 
10. Kapusta, Stofanak - eGlu
10. Kapusta, Stofanak - eGlu10. Kapusta, Stofanak - eGlu
10. Kapusta, Stofanak - eGluMobCon
 
8. Lukas Piska - CN Group
8. Lukas Piska - CN Group8. Lukas Piska - CN Group
8. Lukas Piska - CN GroupMobCon
 
3. Rostislav Simonik - eGlu
3. Rostislav Simonik - eGlu3. Rostislav Simonik - eGlu
3. Rostislav Simonik - eGluMobCon
 
16. Michaela Jacova - Neulogy Ventures
16. Michaela Jacova - Neulogy Ventures16. Michaela Jacova - Neulogy Ventures
16. Michaela Jacova - Neulogy VenturesMobCon
 
Side Room - 3. Skakala, Rostecky - WakesApp.com
Side Room - 3. Skakala, Rostecky - WakesApp.comSide Room - 3. Skakala, Rostecky - WakesApp.com
Side Room - 3. Skakala, Rostecky - WakesApp.comMobCon
 
Side Room - 2. Daniel Novak - Inloop
Side Room - 2. Daniel Novak - InloopSide Room - 2. Daniel Novak - Inloop
Side Room - 2. Daniel Novak - InloopMobCon
 
6. Petr Dvorak - Lime
6. Petr Dvorak - Lime6. Petr Dvorak - Lime
6. Petr Dvorak - LimeMobCon
 
2. Juraj Stankay - Google
2. Juraj Stankay - Google2. Juraj Stankay - Google
2. Juraj Stankay - GoogleMobCon
 
14. Tomas Baran - Goldee
14. Tomas Baran - Goldee14. Tomas Baran - Goldee
14. Tomas Baran - GoldeeMobCon
 
Side Room - 1. Oliver Stahl - Phirational
Side Room - 1. Oliver Stahl - PhirationalSide Room - 1. Oliver Stahl - Phirational
Side Room - 1. Oliver Stahl - PhirationalMobCon
 
15. Viktor Mikulasek - Launcher
15. Viktor Mikulasek - Launcher15. Viktor Mikulasek - Launcher
15. Viktor Mikulasek - LauncherMobCon
 
4. Carlos Conde - Amazon Web Services
4. Carlos Conde - Amazon Web Services4. Carlos Conde - Amazon Web Services
4. Carlos Conde - Amazon Web ServicesMobCon
 
9. Simon Sicko - Pixelfederation
9. Simon Sicko - Pixelfederation9. Simon Sicko - Pixelfederation
9. Simon Sicko - PixelfederationMobCon
 
2871 comparatives and_superlatives
2871 comparatives and_superlatives2871 comparatives and_superlatives
2871 comparatives and_superlativesVanina1234
 
App.t newsletter 1 cz
App.t newsletter 1 czApp.t newsletter 1 cz
App.t newsletter 1 czEUDA_ERA
 
Wh leaping frogs game
Wh   leaping frogs gameWh   leaping frogs game
Wh leaping frogs gameVanina1234
 
Supporting Professional Communities in the Next Web
Supporting Professional Communities in the Next Web Supporting Professional Communities in the Next Web
Supporting Professional Communities in the Next Web Ralf Klamma
 
5. Lubo Smid - STRV
5. Lubo Smid - STRV5. Lubo Smid - STRV
5. Lubo Smid - STRVMobCon
 
19165 hotel _checking_in
19165 hotel _checking_in19165 hotel _checking_in
19165 hotel _checking_inVanina1234
 

Viewers also liked (20)

12. Maros Holly - Sygic
12. Maros Holly - Sygic12. Maros Holly - Sygic
12. Maros Holly - Sygic
 
10. Kapusta, Stofanak - eGlu
10. Kapusta, Stofanak - eGlu10. Kapusta, Stofanak - eGlu
10. Kapusta, Stofanak - eGlu
 
8. Lukas Piska - CN Group
8. Lukas Piska - CN Group8. Lukas Piska - CN Group
8. Lukas Piska - CN Group
 
3. Rostislav Simonik - eGlu
3. Rostislav Simonik - eGlu3. Rostislav Simonik - eGlu
3. Rostislav Simonik - eGlu
 
16. Michaela Jacova - Neulogy Ventures
16. Michaela Jacova - Neulogy Ventures16. Michaela Jacova - Neulogy Ventures
16. Michaela Jacova - Neulogy Ventures
 
Side Room - 3. Skakala, Rostecky - WakesApp.com
Side Room - 3. Skakala, Rostecky - WakesApp.comSide Room - 3. Skakala, Rostecky - WakesApp.com
Side Room - 3. Skakala, Rostecky - WakesApp.com
 
Side Room - 2. Daniel Novak - Inloop
Side Room - 2. Daniel Novak - InloopSide Room - 2. Daniel Novak - Inloop
Side Room - 2. Daniel Novak - Inloop
 
6. Petr Dvorak - Lime
6. Petr Dvorak - Lime6. Petr Dvorak - Lime
6. Petr Dvorak - Lime
 
2. Juraj Stankay - Google
2. Juraj Stankay - Google2. Juraj Stankay - Google
2. Juraj Stankay - Google
 
14. Tomas Baran - Goldee
14. Tomas Baran - Goldee14. Tomas Baran - Goldee
14. Tomas Baran - Goldee
 
Side Room - 1. Oliver Stahl - Phirational
Side Room - 1. Oliver Stahl - PhirationalSide Room - 1. Oliver Stahl - Phirational
Side Room - 1. Oliver Stahl - Phirational
 
15. Viktor Mikulasek - Launcher
15. Viktor Mikulasek - Launcher15. Viktor Mikulasek - Launcher
15. Viktor Mikulasek - Launcher
 
4. Carlos Conde - Amazon Web Services
4. Carlos Conde - Amazon Web Services4. Carlos Conde - Amazon Web Services
4. Carlos Conde - Amazon Web Services
 
9. Simon Sicko - Pixelfederation
9. Simon Sicko - Pixelfederation9. Simon Sicko - Pixelfederation
9. Simon Sicko - Pixelfederation
 
2871 comparatives and_superlatives
2871 comparatives and_superlatives2871 comparatives and_superlatives
2871 comparatives and_superlatives
 
App.t newsletter 1 cz
App.t newsletter 1 czApp.t newsletter 1 cz
App.t newsletter 1 cz
 
Wh leaping frogs game
Wh   leaping frogs gameWh   leaping frogs game
Wh leaping frogs game
 
Supporting Professional Communities in the Next Web
Supporting Professional Communities in the Next Web Supporting Professional Communities in the Next Web
Supporting Professional Communities in the Next Web
 
5. Lubo Smid - STRV
5. Lubo Smid - STRV5. Lubo Smid - STRV
5. Lubo Smid - STRV
 
19165 hotel _checking_in
19165 hotel _checking_in19165 hotel _checking_in
19165 hotel _checking_in
 

Side Room - 5. Alex Wald - Inloop

  • 2. FUNCTIONAL • stateless; state is derived instead
 (cell c = cell a + cell b) • immmmmmmmutable data • dôraz na high-order funkcie (ktoré produkujú vyýstup na základe vstupov) • funkcie ako 1st class objekty
  • 4. REACTIVE • práca s asynchrónnymi data streams • …taktiež s nested callbacks, complexnými list filtering/ transformáciami alebo timing concerns • integruje koncept času a kompozíciu udalostí spolu s funkcionálnym programovaním. • od MS, spolu aj s MVVM
  • 5. ReactiveCocoa • obj-c / swift implementácia pre iOS & Mac OS X • zjednocuje programovacie API pre všetky eventy • KVO, delegate, notifications, block syntax, target-action • od 3.0 podpora Swift
  • 6. BUILDING BLOCKS RACSequence RACSignal Stream • push-driven stream• pull-driven stream • oba zdieľajú viacero spoločných operátorov
  • 7. RACSequence • lazily-loaded kolekcie • podobný účel ako NSArray • pridáva funkcie, ktoré Foundatin nemá: map*, filter, fold/reduce… • objekty kolekcie netransformujú, až kým nie sú vytiahnuté (for-in, etc.) RACSequence *normalizedLongWords = [[words.rac_sequence filter:^ BOOL (NSString *word) { return [word length] >= 10; }] map:^(NSString *word) { return [word lowercaseString]; }]; * swift už map vie
  • 8. RACSignal • rúra, ktora nesie hodnotu ( input > transform > output ) • signály môžu byť (a budú) reťazené (funkcia pojme funkciu) • Chaining of Dependent Operations • Parallelizing Independent Work • (Hint *) Signály sú interne postavené na KVO
  • 9. RACSignal (cont.) • signál posiela 3 druhy eventov: next, finished, error • next nesie naše dáta ( = čokoľvek) • Subscribe (na základe čoho robíme side-effects) • binding pomocou RAC() • nahradzujú @property (niekedy) • neprepisuje/nemodifikuje pôvodný stream. (immutability) • 0, 1, alebo > 1 subscriberov • alebo si ich vytvoríme: RACObserve() (zabalí dynamickú property)
  • 10. RACSignal  *formValid  =  [RACSignal          combineLatest:@[   self.username.rac_textSignal,   self.emailField.rac_textSignal,   self.passwordField.rac_textSignal,   self.passwordVerificationField.rac_textSignal   ]   reduce:^(NSString  *username,  NSString  *email,  NSString  *password,  NSString   *passwordVerification)  {          return  @([username  length]  >  0  &&  [email  length]  >  0  &&  [password  length]  >   8  &&  [password  isEqual:passwordVerification]);   }];   RAC(self.createButton.enabled)  =  formValid; emailField userNameField passwordVerifi cationField passwordField combineLatest reduce formValid NSNumber (boolean) NSString NSString NSString NSString 4x NSString
  • 11. -­‐  (RACCommand*)rac_searchCommand   {          if  (!_searchCommand)  {                  @weakify(self)                  _searchCommand  =  [[RACCommand  alloc]  initWithSignalBlock:^RACSignal  *(NSDictionary   *parameters)  {                                                                    @strongify(self)                          return  [[self.searchHelper  rac_searchWithScheduler:[RACScheduler  scheduler]   parameters]  catch:^RACSignal  *(NSError  *error)  {                                  DLog(@"Remote  Search  Error");                                  return  [RACSignal  return:RACTuplePack(@[])];                          }];                  }];          }          return  _searchCommand;   } -­‐  (void)viewModelSetup   {          [[[self.rac_searchCommand  executionSignals]  flatten]          subscribeNext:^(NSArray  *  array)  {                          [self.data  =  array];          }];   } ViewModel
  • 12. func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { ... cell.model = searchVM!.modelForResultAtIndexPath(indexPath) ... return cell }        override  func  viewDidLoad()  {                  RACObserve(self.searchVM,  "data").ignore(nil).subscribeNext  {  [unowned  self]  (any)  -­‐>   Void  in                          self.searchResultsTable.reloadData()                }          } func searchBarSearchButtonClicked(searchBar: UISearchBar) { println("search (searchBar.text)") self.searchVM?.rac_searchCommand.execute(["query" : searchBar.text]) } ViewController searchButton.enabled <~ viewModel.rac_searchCommand.executing
  • 13. -­‐  (void)awakeFromNib  {          RAC(self.titleLabel,  text)  =  [RACObserve(self,  model.title)  ignore:nil];          RACSignal  *  colorSignal  =  [[RACObserve(self,sectionModel.sectionColorRGBString)   ignore:nil]  map:^id(NSString*  value)  {                  return  [UIColor  colorFromString:value];          }];          RAC(self.resultImage,  backgroundColor)  =  colorSignal;   } TableViewCell
  • 14. SWIFT let usernameTextField: UITextField = UITextField() usernameTextField.rac_textSignal() .mapAs { (text: NSString) -> NSNumber in return text.length }.filterAs { (number: NSNumber) -> Bool in return number > 3 }.subscribeNextAs { (length: NSNumber) in println(length) } OBJ-C UITextField *usernameTextField = [[UITextField alloc] init]; [[[usernameTextField.rac_textSignal map:^(NSString *value) { return @(value.length); }] filter:^BOOL(NSNumber *value) { return value > 0; }] subscribeNext:^(NSNumber *length) { NSLog(@"%d", [length intValue]); }];
  • 15. Fluent API [[[[[[[[[[[[[[[[I dont] think] fluent] interface] patterns] will] be] useful] unless] you] want] to] write] methods] like] this];