Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Brooklyn iOS Developer Meetup February 2014

Brooklyn iOS Developer Meetup February 2014

Robert Böhnke

February 19, 2014
Tweet

More Decks by Robert Böhnke

Other Decks in Programming

Transcript

  1. Have you tried turning it off and on again? Have

    you tried turning it off and on again?
  2. 
 
 ! ! - (void)setQuacks:(BOOL)quacks { _quacks = quacks;

    
 self.duck = quacks && self.walks;
 } - ( _walks = walks; 
 self.duck = walks }
  3. RAC(self, duck) = [RACSignal
 combineLatest:@[
 RACObserve(self, walks),
 RACObserve(self, quacks)
 ]]


    reduce:^(NSNumber *walks, NSNumber *quacks) {
 return @(walks.boolValue &&
 quacks.boolValue);
 }];
  4. RAC(self, duck) = [RACSignal
 combineLatest:@[
 RACObserve(self, walks),
 RACObserve(self, quacks)
 ]]


    reduce:^(NSNumber *walks, NSNumber *quacks) {
 return @(walks.boolValue &&
 quacks.boolValue);
 }];
  5. RAC(self, duck) = [RACSignal
 combineLatest:@[
 RACObserve(self, walks),
 RACObserve(self, quacks)
 ]]


    reduce:^(NSNumber *walks, NSNumber *quacks) {
 return @(walks.boolValue &&
 quacks.boolValue);
 }];
  6. RAC(self, duck) = [RACSignal
 combineLatest:@[
 RACObserve(self, walks),
 RACObserve(self, quacks)
 ]]


    reduce:^(NSNumber *walks, NSNumber *quacks) {
 return @(walks.boolValue &&
 quacks.boolValue);
 }];
  7. map

  8. - (void)textFieldTextDidChange:(UITextField *)field {
 BOOL validUsername = self.username.text.length > 0;


    
 NSRange at = [self.email.text rangeOfString:@"@"];
 
 BOOL validEmail = at.location != NSNotFound;
 self.signupButton.enabled = validUsername &&
 validEmail;
 }
  9. - (void)textFieldTextDidChange:(UITextField *)field {
 BOOL validUsername = self.username.text.length > 0;


    
 NSRange at = [self.email.text rangeOfString:@"@"];
 
 BOOL validEmail = at.location != NSNotFound;
 self.signupButton.enabled = validUsername &&
 validEmail;
 }
  10. RAC(self.signUpButton, enabled) = [RACSignal
 combineLatest:@[
 self.name.rac_textSignal
 self.email.rac_textSignal
 ]]
 reduce:^(NSString *name,

    NSString *email) {
 NSRange at = [email rangeOfString:@"@"]; ! return @(at.location != NSNotFound && name.length > 0);
 }]:
  11. RAC(self.signUpButton, enabled) = [RACSignal
 combineLatest:@[
 self.name.rac_textSignal
 self.email.rac_textSignal
 ]]
 reduce:^(NSString *name,

    NSString *email) {
 NSRange at = [email rangeOfString:@"@"]; ! return @(at.location != NSNotFound && name.length > 0);
 }]:
  12. RAC(self.signUpButton, enabled) = [RACSignal
 combineLatest:@[
 self.name.rac_textSignal
 self.email.rac_textSignal
 ]]
 reduce:^(NSString *name,

    NSString *email) {
 NSRange at = [email rangeOfString:@"@"]; ! return @(at.location != NSNotFound && name.length > 0);
 }]:
  13. RAC(self.signUpButton, enabled) = [RACSignal
 combineLatest:@[
 self.name.rac_textSignal
 self.email.rac_textSignal
 ]]
 reduce:^(NSString *name,

    NSString *email) {
 NSRange at = [email rangeOfString:@"@"]; ! return @(at.location != NSNotFound && name.length > 0);
 }]:
  14. [client logInWithSuccess:^{ [client loadMeUserWithSuccess:^(SPUser *me) { [client loadNewslettersForUser:me withSuccess:^(NSArray *newsletters)

    { NSLog(@"Help me, " "I'm trapped in callback hell!"); } error:^(NSError *error) { // Handle failure } } error:^(NSError *error) { // Handle failure }];
 } error:^(NSError *error) { // Handle failure }];
  15. [client logInWithSuccess:^{ [client loadMeUserWithSuccess:^(SPUser *me) { [client loadNewslettersForUser:me withSuccess:^(NSArray *newsletters)

    { NSLog(@"Help me, " "I'm trapped in callback hell!"); } error:^(NSError *error) { // Handle failure } } error:^(NSError *error) { // Handle failure }];
 } error:^(NSError *error) { // Handle failure }]; omg, why?!
  16. [self enqueueHTTPRequestOperation:operation]; ! - (RACSignal *)enqueueRequest:(NSURLRequest *)req {
 return [RACSignal

    createSignal:^(id<RACSubscriber> subscriber) { AFHTTPRequestOperation *operation; operation = [self HTTPRequestOperationWithRequest:req success:^(id operation, id response) { [subscriber sendNext:response]; [subscriber sendCompleted]; }} failure:^(id operation, NSError *error) { [subscriber sendError:error]; }];
  17. - (RACSignal *)enqueueRequest:(NSURLRequest *)req {
 return [RACSignal createSignal:^(id<RACSubscriber> subscriber) {

    AFHTTPRequestOperation *operation; operation = [self HTTPRequestOperationWithRequest:req success:^(id operation, id response) { [subscriber sendNext:response]; [subscriber sendCompleted]; }} failure:^(id operation, NSError *error) { [subscriber sendError:error]; }]; [self enqueueHTTPRequestOperation:operation]; !
  18. [self enqueueHTTPRequestOperation:operation]; ! - (RACSignal *)enqueueRequest:(NSURLRequest *)req {
 return [RACSignal

    createSignal:^(id<RACSubscriber> subscriber) { AFHTTPRequestOperation *operation; operation = [self HTTPRequestOperationWithRequest:req success:^(id operation, id response) { [subscriber sendNext:response]; [subscriber sendCompleted]; }} failure:^(id operation, NSError *error) { [subscriber sendError:error]; }];
  19. - (RACSignal *)enqueueRequest:(NSURLRequest *)req {
 return [RACSignal createSignal:^(id<RACSubscriber> subscriber) {

    AFHTTPRequestOperation *operation; operation = [self HTTPRequestOperationWithRequest:req success:^(id operation, id response) { [subscriber sendNext:response]; [subscriber sendCompleted]; }} failure:^(id operation, NSError *error) { [subscriber sendError:error]; }]; [self enqueueHTTPRequestOperation:operation]; !
  20. - (RACSignal *)enqueueRequest:(NSURLRequest *)req {
 return [RACSignal createSignal:^(id<RACSubscriber> subscriber) {

    AFHTTPRequestOperation *operation; operation = [self HTTPRequestOperationWithRequest:req success:^(id operation, id response) { [subscriber sendNext:response]; [subscriber sendCompleted]; }} failure:^(id operation, NSError *error) { [subscriber sendError:error]; }]; [self enqueueHTTPRequestOperation:operation]; !
  21. [self enqueueHTTPRequestOperation:operation]; ! return [RACDisposable disposableWithBlock:^{ [operation cancel]; }]; }];

    success:^( [subscriber sendNext:response]; [subscriber sendCompleted]; } failure:^( [subscriber sendError:error]; }];
  22. [self enqueueHTTPRequestOperation:operation]; ! return [RACDisposable disposableWithBlock:^{ [operation cancel]; }]; }];

    success:^( [subscriber sendNext:response]; [subscriber sendCompleted]; } failure:^( [subscriber sendError:error]; }];
  23. - (RACSignal *)fetchMeUser
 return [[self.client getPath:@"/me"] flattenMap:^(id JSON) { NSError

    *error; SPUser *user = [SPUser userWithJSON:JSON
 error:&error];
 if (user == nil) {
 return [RACSignal error:error];
 } else {
 return [RACSignal return:user];
 }} }];
 }}
  24. - (RACSignal *)fetchMeUser
 return [[self.client getPath:@"/me"] flattenMap:^(id JSON) { NSError

    *error; SPUser *user = [SPUser userWithJSON:JSON
 error:&error];
 if (user == nil) {
 return [RACSignal error:error];
 } else {
 return [RACSignal return:user];
 }} }];
 }}
  25. - (RACSignal *)fetchMeUser
 return [[self.client getPath:@"/me"] flattenMap:^(id JSON) { NSError

    *error; SPUser *user = [SPUser userWithJSON:JSON
 error:&error];
 if (user == nil) {
 return [RACSignal error:error];
 } else {
 return [RACSignal return:user];
 }} }];
 }}
  26. - (RACSignal *)fetchMeUser
 return [[self.client getPath:@"/me"] flattenMap:^(id JSON) { NSError

    *error; SPUser *user = [SPUser userWithJSON:JSON
 error:&error];
 if (user == nil) {
 return [RACSignal error:error];
 } else {
 return [RACSignal return:user];
 }} }];
 }}
  27. - (RACSignal *)fetchMeUser
 return [[self.client getPath:@"/me"] flattenMap:^(id JSON) { NSError

    *error; SPUser *user = [SPUser userWithJSON:JSON
 error:&error];
 if (user == nil) {
 return [RACSignal error:error];
 } else {
 return [RACSignal return:user];
 }} }];
 }} check out Mantle!

  28. - (RACSignal *)fetchMeUser
 return [[self.client getPath:@"/me"] flattenMap:^(id JSON) { NSError

    *error; SPUser *user = [SPUser userWithJSON:JSON
 error:&error];
 if (user == nil) {
 return [RACSignal error:error];
 } else {
 return [RACSignal return:user];
 }} }];
 }}
  29. - (RACSignal *)fetchMeUser
 return [[self.client getPath:@"/me"] flattenMap:^(id JSON) { NSError

    *error; SPUser *user = [SPUser userWithJSON:JSON
 error:&error];
 if (user == nil) {
 return [RACSignal error:error];
 } else {
 return [RACSignal return:user];
 }} }];
 }}
  30. [[[[client logIn] then:^{ return [client fetchMeUser]; }] flattenMap:^(SPUser *me) {

    return [client fetchNewslettersForUser:me]; }] subscribeNext:^(NSArray *files) { NSLog(@"Files: %@", files); }}
 error:^(NSError *error) { // Handle error }];
  31. [[[[client logIn] then:^{ return [client fetchMeUser]; }] flattenMap:^(SPUser *me) {

    return [client fetchNewslettersForUser:me]; }] subscribeNext:^(NSArray *files) { NSLog(@"Files: %@", files); }}
 error:^(NSError *error) { // Handle error }];
  32. [[[[client logIn] then:^{ return [client fetchMeUser]; }] flattenMap:^(SPUser *me) {

    return [client fetchNewslettersForUser:me]; }] subscribeNext:^(NSArray *files) { NSLog(@"Files: %@", files); }}
 error:^(NSError *error) { // Handle error }];
  33. [[[[client logIn] then:^{ return [client fetchMeUser]; }] flattenMap:^(SPUser *me) {

    return [client fetchNewslettersForUser:me]; }] subscribeNext:^(NSArray *files) { NSLog(@"Files: %@", files); }}
 error:^(NSError *error) { // Handle error }];
  34. [[[[client logIn] then:^{ return [client fetchMeUser]; }] flattenMap:^(SPUser *me) {

    return [client fetchNewslettersForUser:me]; }] subscribeNext:^(NSArray *files) { NSLog(@"Files: %@", files); }}
 error:^(NSError *error) { // Handle error }];
  35. [[[[client logIn] then:^{ return [client fetchMeUser]; }] flattenMap:^(SPUser *me) {

    return [client fetchNewslettersForUser:me]; }] subscribeNext:^(NSArray *files) { NSLog(@"Files: %@", files); }}
 error:^(NSError *error) { // Handle error }];
  36. RAC(self.signUpButton, enabled) = [RACSignal
 combineLatest:@[
 
 
 ]] 
 


    
 
 self.name.rac_textSignal,
 self.email.rac_textSignal reduce:^(NSString *name, NSString *email) {
 NSRange at = [email rangeOfString:@"@"];
 return @(at.location != NSNotFound &&
 name.length > 0);
 }];
  37. RAC(self.signUpButton, enabled) = [RACSignal
 combineLatest:@[
 
 
 ]] 
 


    
 
 self.name.rac_textSignal,
 self.email.rac_textSignal reduce:^(NSString *name, NSString *email) {
 NSRange at = [email rangeOfString:@"@"];
 return @(at.location != NSNotFound &&
 name.length > 0);
 }];
  38. RAC(self.signUpButton, enabled) = [RACSignal
 combineLatest:@[
 
 
 ]] 
 


    
 
 validName,
 validEmail reduce:^(NSString *name, NSString *email) {
 NSRange at = [email rangeOfString:@"@"];
 return @(at.location != NSNotFound &&
 name.length > 0);
 }];
  39. RAC(self.signUpButton, enabled) = [RACSignal
 combineLatest:@[
 
 
 ]] 
 


    
 
 validName,
 validEmail reduce:^(NSString *name, NSString *email) {
 NSRange at = [email rangeOfString:@"@"];
 return @(at.location != NSNotFound &&
 name.length > 0);
 }];
  40. RAC(self.signUpButton, enabled) = [RACSignal
 combineLatest:@[
 
 
 ]] 
 


    
 
 validName,
 validEmail reduce:^(NSNumber *name, NSNumber *email) {
 return @(name.boolValue && email.boolValue);
 }]; }];
 

  41. RAC(self.signUpButton, enabled) = [RACSignal combineLatest: 
 
 
 
 validName,

    validEmail reduce:^(NSNumber *name, NSNumber *email) { RACSignal *validName = [self.name.rac_textSignal map:^(NSString *name) { return @(name.length > 0); }];
 
 switchToLatest];
 

  42. RACSignal *validName = [self.name.rac_textSignal map:^(NSString *name) { return }] 


    RACSignal *validEmail = [[self.email.rac_textSignal map:^(NSString *email) { return [[client validateEmail:email] startWith:@NO]; }] switchToLatest];
 

  43. RACSignal *validName = [self.name.rac_textSignal map:^(NSString *name) { return }] 


    RACSignal *validEmail = [[self.email.rac_textSignal map:^(NSString *email) { return [[client validateEmail:email] startWith:@NO]; }] switchToLatest];
 

  44. RACSignal *validName = [self.name.rac_textSignal map:^(NSString *name) { return }] 


    RACSignal *validEmail = [[self.email.rac_textSignal map:^(NSString *email) { return [[client validateEmail:email] startWith:@NO]; }] switchToLatest];
 

  45. + Declarative code + Easy handling of asynchronous tasks +

    Great Composition − Conceptual overhead Recap
  46. + Declarative code + Easy handling of asynchronous tasks +

    Great Composition − Conceptual overhead − Debugging can get tricky Recap
  47. + Declarative code + Easy handling of asynchronous tasks +

    Great Composition − Conceptual overhead − Debugging can get tricky Recap (dtrace support)
  48. Qs?

  49. iPhone 5 Sketch Template
 courtesy of
 Denis Rojčyk ! Cloud

    icon
 curtesy of Dmitry Baranovskiy, from The Noun Project