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

iOS backend wrappers for hipsters

iOS backend wrappers for hipsters

I describe the approach, frameworks & tools which we are using at Wargaming.net to communicate with our backend APIs

Denis Lebedev

November 02, 2013
Tweet

More Decks by Denis Lebedev

Other Decks in Programming

Transcript

  1. Agenda • What we do! • Code & libs! •

    Infrastructure & tools! • Distribution
  2. Service Mobile Apps department • “Assistant” apps for player engagement!

    • One of the largest WG API consumers! • Quality is one of the main goals! • New tools & approaches are welcome
  3. WGNAPIClient • Separate project! • Developed with love & unit

    tests in mind! • Will be open sourced some day
  4. Requirements • Different cache invalidation time for entities! • Wraps

    every available method of API! • As stable as possible (API “unexpectedly changes”)! • Supports “partial entities”! • Out-of-the-box usage
  5. WGNAPIClient 0.5 • Based on AFNetworking! • Only WOT API!

    • Core Data as cache system (tried even SQL)! • “Manual” entities parsing! • Extremely low code reuse! • Unit tests code is awful
  6. Async CoreData cache • NSManagedObjectIDs here and there! • Tries

    to fetch existing item with ID and updates it if it exists! • Object-graph is only partially filled
  7. Old-school parsing WOWPPlane *plane = [[WOWPPlane alloc] init]; ! plane.name

    = json[@“name"]; ! if ([json[@"type"] isEqualToString:@"assault"]) { plane.type = WOWPPlaneTypeAssault; } else { plane.type = WOWPPlaneTypeFighter; } ! plane.priceCredit = json[@"price"];
  8. What? • Composes and transforms streams of values! • Functional

    Reactive Programming in Obj-C http://en.wikipedia.org/wiki/ Functional_reactive_programming
  9. Signals • Represent data that will be delivered later! •

    Can be chained/merged! • Have optional next/error/completed “callbacks”
  10. [[RACObserve(self, language) ! filter:^(NSString *newName) { return [newName hasPrefix:@"j"]; }]

    ! subscribeNext:^(NSString *newName) { NSLog(@"%@", newName); }];
  11. Not so nested callbacks ! [[[[WOTClient sharedClient] fetchPlayers:nil] ! flattenMap:^RACStream

    *(NSArray *players) { return [[WOTClient sharedClient] fetchClans:nil]; ! }] flattenMap:^RACStream *(id clans) { return [[WOTClient sharedClient] fetchClans:nil]; }];
  12. One point of error/result handling ! [[[[[WOTClient sharedClient] fetchPlayers:nil] !

    flattenMap:^RACStream *(NSArray *players) { return [[WOTClient sharedClient] fetchClans:nil]; ! }] flattenMap:^RACStream *(id clans) { return [[WOTClient sharedClient] fetchClans:nil]; ! }] subscribeNext:^(id tanks) { //success } error:^(NSError *error) { //error }];
  13. Under the hood - (RACSignal *)fetchPlanesWithFields:(NSArray *)fields { ! return

    [self getPath:@“encyclopedia/planes" ! parameters:@{@"fields": PARAM(fields)} ! resultClass:WOWPShortPlane.class]; }
  14. Caching 2.0 • Say “NO” to CoreData! • Cache all

    the things! • Uniform approach for any entity
  15. Mantle benefits • Maps backend entities to model layer! •

    Nested models! • Attribute transformers! • NSManagedObject support! • Implements <NSCoding>
  16. NSURLCache • Works on the network protocol level! • Caches

    response by it’s URL! • 2 LOC to implement* NSURLCache *urlCache = [[NSURLCache alloc] initWithMemoryCapacity:kInMemoryCacheSize diskCapacity:kOnDiskCacheSize diskPath:path]; [NSURLCache setSharedURLCache:urlCache];
  17. Tweak NSURLCache • Add necessary cache headers on client side!

    • Full control of caching time! • Reference implementation: https:// gist.github.com/garnett/7266332
  18. stubResponse(@"account/list", @“players.json"); ! RACSignal *searchRequest = [client searchPlayers:@"garnett" limit:0]; !

    NSArray *response = [searchRequest asynchronousFirstOrDefault:nil success:&success error:&error]; ! [error shouldBeNil]; [[response should] beKindOfClass:NSArray.class]; [[response should] haveCountOf:3];
  19. xctool • Same interface as in xcodebuild! • No mess

    with simulator! • Fancy (or even custom) build output