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

Some Code Patterns

Some Code Patterns

VIDEO: https://vimeo.com/124773343

This talk covers a handful of code patterns that were successful on my recent projects. Some of these patterns include Block Safety, "Tell, Don't Ask", Using DataSources for your network-based *Service objects.

Mike Zornek

April 09, 2015
Tweet

More Decks by Mike Zornek

Other Decks in Programming

Transcript

  1. // .h extern NSString * const StoryboardNameSettings; // .m NSString

    * const StoryboardNameSettings = @"Settings"; // use new constant UIStoryboard *storyboard = [UIStoryboard storyboardWithName:StoryboardNameSettings bundle:nil];
  2. @implementation UIStoryboard (Additions) + (UIStoryboard *)pch_settingsStoryboard { if ( UI_USER_INTERFACE_IDIOM()

    == UIUserInterfaceIdiomPad ) return [UIStoryboard storyboardWithName:@"Settings~iPad" bundle:nil]; } else { return [UIStoryboard storyboardWithName:@"Settings~iPhone" bundle:nil]; } } @end
  3. #define ERROR_DOMAIN @"com.mikezornek.json-parser" @implementation NSError (MZJSONParserErrors) + (NSError *)mdz_invalidJsonError {

    return [NSError errorWithDomain:ERROR_DOMAIN code:1001 userInfo:@{NSLocalizedDescriptionKey : @"JSON was malformed and could not be parsed."}]; } @end
  4. // In even a simple network call this can get

    out of hand... - (void)downloadTracksFromURL:(NSURL *)url completionHandler:(void (^)(NSArray *tracks, NSError *error))completion { NSURLSessionDataTask *dataTask = [self.session dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (!error) { NSError *trackError; NSArray *tracks = [self tracksFromData:data error:&trackError]; if (tracks) { if (completionHandler) { completionHandler(tracks, nil); } } else { if (completionHandler) { completionHandler(nil, trackError); } } } else { if (completionHandler) { completionHandler(nil, error); } } }]; [dataTask resume]; }
  5. // Look how nicer it gets when you can assume

    the block is present... - (void)downloadTracksFromURL:(NSURL *)url completionHandler: (void (^)(NSArray *tracks, NSError *error))completion { // Some code or method to verify the completion block is not null NSURLSessionDataTask *dataTask = [self.session dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (!error) { NSError *trackError; NSArray *tracks = [self tracksFromData:data error:&trackError]; tracks ? completionHandler(tracks, nil) : completionHandler(nil, trackError); } else { completionHandler(nil, error); } }]; [dataTask resume]; }
  6. DEFAULT BLOCK - (void)processPhoneList:(NSArray *)list completion: (PhoneListCompletionHandler)incomingCompletion { PhoneListCompletionHandler completion

    = (incomingCompletionHandler != NULL) ? incomingCompletionHandler : ^{ NSLog(@"processPhoneList: did complete"); }; // When the time comes, look ma' no need to check for nil! completion() }
  7. NEW IN XCODE 6.31 // as long as the type

    is a simple object or block pointer. - (nullable AAPLListItem *)itemWithName:(nonnull NSString *)name; - (NSInteger)indexOfItem:(nonnull AAPLListItem *)item; 1 https://developer.apple.com/swift/blog/?id=25
  8. NEW IN XCODE 6.31 @property (copy, nullable) NSString *name; @property

    (copy, readonly, nonnull) NSArray *allItems; 1 https://developer.apple.com/swift/blog/?id=25
  9. The core idea of the Tell, Don't Ask pattern is

    that any *ViewController or *Service or *Store you build should, when initialized or otherwise "prepared", have all the information it needs to do its job. It should not ask the global state for information. -- Mike Zornek, right now
  10. But I don't want to manually pass around all these

    state objects! — Someone complained
  11. struct LaunchMenuItem { let title: String let details: String let

    runAction: () -> () } struct LaunchMenuSection { let title: String let items: [LaunchMenuItem] } struct LaunchMenu { let sections: [LaunchMenuSection] }