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

iOS. Advanced programming techniques

iOS. Advanced programming techniques

Василь Кричун Project Manger/Solution Architect at Malkos
iOS. Advanced programming techniques
Доповідь містить практичні приклади нестандартних рішень для розробки iOS додатків і розрахована на осіб, які мають базові або середні знання в iOS програмуванні. Будуть розглянуті архітектурні рішення для багатопотокових додатків, можливості Objective-C Runtime, CoreData, способи оптимізації та інші корисні речі.

Grygoriy Mykhalyuno

May 17, 2014
Tweet

More Decks by Grygoriy Mykhalyuno

Other Decks in Programming

Transcript

  1. MVC

  2. Native bridge
 (approach #1) Native: - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request

    navigationType: (UIWebViewNavigationType)navigationType; ! JS: window.location = http://something.com?func=<name of func>&params='list of params (json)'&callback=jsFunc;
  3. - (NSDictionary*) sendRequest: (NSURLRequest*) request { _connecion = [[NSURLConnection alloc]

    initWithRequest: request delegate:self startImmediately:NO]; NSRunLoop *runLoop = [NSRunLoop currentRunLoop]; [_connecion scheduleInRunLoop:runLoop forMode:NSDefaultRunLoopMode]; [_connecion start]; do { [runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; } while (!_isDone && !_isCanceled); [_connecion cancel]; return _responseData; } Synchronous request
  4. + (NSSet *)keyPathsForValuesAffectingSynchronized { unsigned int num_props; objc_property_t *prop_list =

    class_copyPropertyList(self, &num_props); NSMutableSet * propSet = [NSMutableSet set]; for( unsigned int i = 0; i < num_props; i++ ) { NSString * propName = [NSString stringWithFormat:@"%s", property_getName(prop_list[i])]; if(![propName isEqualToString:@"synchronized"] ) { [propSet addObject:propName]; } } free(prop_list); return propSet; } KVO
  5. Tricks • Method swizzling • Network operations when app in

    background • Blocks as arguments • Device unique identifier !
  6. Method swizzling Class class = [self class]; SEL originalSelector =

    @selector(viewWillAppear:); SEL swizzledSelector = @selector(own_viewWillAppear:); Method originalMethod = class_getInstanceMethod(class, originalSelector); Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector); method_exchangeImplementations(originalMethod, swizzledMethod);
  7. App in background UIApplication *app = [UIApplication sharedApplication]; __block UIBackgroundTaskIdentifier

    bgTask; bgTask = [app beginBackgroundTaskWithExpirationHandler:^{ NSLog(@"background task has ended"); [app endBackgroundTask:bgTask]; }];
  8. Blocks as arguments - (void) downloadFile: (NSURL*) url options: (NSDictionary*)

    options completionBlock:(void(^)(BOOL result)) completionBlock progressBlock:(void(^)(long long data_size, long long downloaded_data_size)) progressBlock; ! typedef void (^CompletionEvent) (BOOL result); typedef void (^ProgressEvent) (long long data_size, long long downloaded_data_size); ! - (void) downloadFile: (NSURL*) url options: (NSDictionary*) options completionBlock:(CompletionEvent) completionBlock progressBlock:(ProgressEvent) progressBlock;
  9. Blocks as arguments - (void) downloadFile: (NSURL*) url options: (NSDictionary*)

    options completionBlock:(CompletionEvent) completionBlock progressBlock:(ProgressEvent) progressBlock { //downloading is completed completionBlock (YES); //downloading in progress progressBlock(123334,456); } ! [self downloadFile:url options:options completionBlock:^(BOOL result) { if (result) { //DO smth. } } progressBlock:^(long long data_size, long long downloaded_data_size) { //handle data_size and downloaded_data_size }];
  10. Device unique Id + (NSString*) getUniqueDeviceIdentifier { KeychainItemWrapper *wrapper =

    [[KeychainItemWrapper alloc] initWithIdentifier:@"yourApplication" accessGroup:nil]; [wrapper setObject:(__bridge id)kSecAttrAccessibleAlways forKey:(__bridge id)kSecAttrAccessible]; NSString *uniqueIdentifier = [wrapper objectForKey:(__bridge id)kSecAttrAccount]; if (!uniqueIdentifier || [uniqueIdentifier length] == 0) { CFUUIDRef newUniqueId = CFUUIDCreate(kCFAllocatorDefault); uniqueIdentifier = (__bridge_transfer NSString*)CFUUIDCreateString(kCFAllocatorDefault, newUniqueId); CFRelease(newUniqueId); [wrapper setObject:uniqueIdentifier forKey:(__bridge id)kSecAttrAccount]; } return uniqueIdentifier; }