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, способи оптимізації та інші корисні речі.

Avatar for Grygoriy Mykhalyuno

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; }