Some Closure After Missing the Block Party

Some Closure After Missing the Block Party

Blocks are a powerful programming pattern introduced in iOS 4. Block-based APIs are used throughout the system now and you really need to be comfortable with the concept, especially with Swift on the horizon. We’ll take a look at the key concepts needed to work with blocks, some of the frameworks like Grand Central Dispatch that make them powerful, and then see how they’re evolving in Swift.

9b54e5324785eb939bcc8f15c724baf9?s=128

Curtis Herbert

June 12, 2014
Tweet

Transcript

  1. Some Closure After Missing the Block Party Curtis Herbert @parrots

  2. What is a block?

  3. ^() { //do some awesome stuff };

  4. void (^myBlock)() = ^() { NSLog(@“Inside!”); }; ! NSLog(@“Outside”); !

    myBlock();
  5. int (^myBlock)(int) = ^(int a) { return a * 15;

    }; ! int result = myBlock(10);
  6. int (^myBlock)(int) = ^(int a) { return a * 15;

    }; ! int result = myBlock(10); Definition Implementation Return type Name Parameters Body Parameter types
  7. int (^myBlock)(int) = ^(int a) { return a * 15;

    }; ! int result = myBlock(10); Definition Implementation Return type Name Parameters Body Parameter types
  8. int (^myBlock)(int) = ^(int a) { return a * 15;

    }; ! int result = myBlock(10); Definition Implementation Return type Name Para Body Parameter types
  9. int (^myBlock)(int) = ^(int a) { return a * 15;

    }; ! int result = myBlock(10); Definition Implementation Return type Name Parameter types Body Parameters
  10. int (^myBlock)(int) = ^(int a) { return a * 15;

    }; ! int result = myBlock(10); Definition Implementation Return type Name Parameter types Parameters Body
  11. http://f*ckingblocksyntax.com ! ! (or http://goshdarnblocksyntax.com)

  12. [UIView animateWithDuration:1 animations:^{ self.view.alpha = 0.0; }]; ! ! [myDictionary

    enumerateKeysAndObjectsUsingBlock: ^(id k, id v, BOOL *stop) { NSLog(@"%@ => %@", k, v); }];
  13. - (void)upload:(NSData *)data failure:(void (^)(NSError *))callback; ! ! ! [server

    upload:myData failure:^(NSError *error) { NSLog(@“Error!?! %@“, error); }];
  14. Blocks + Grand Central Dispatch

  15. Queue Types Concurrent Serial 1 2 3 1 2 3

  16. dispatch_get_global_queue() (concurrent) • DISPATCH_QUEUE_PRIORITY_BACKGROUND • DISPATCH_QUEUE_PRIORITY_LOW • DISPATCH_QUEUE_PRIORITY_NORMAL • DISPATCH_QUEUE_PRIORITY_HIGH

    dispatch_get_main_queue() (serial) dispatch_queue_create();
  17. - (void)doLotsOfWork { for (int i = 1; i <

    100000; i++) { NSLog(@“%l”, i); } } ! ... ! NSLog(@“Before”); ! [self doLotsOfWork]; ! NSLog(@“After”);
  18. Don’t block the main thread!

  19. NSLog(@“Before”); ! [self performSelectorInBackground: @selector(doLotsOfWork) withObject:nil]; ! NSLog(@“After”);

  20. dispatch_async

  21. NSLog(@“Before”); ! dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ //Background Task for (int

    i = 1; i < 100000; i++) { NSLog(@“%l”, i); } } ); ! NSLog(@“After”);
  22. NSLog(@“Before”); ! dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ //Background Task for (int

    i = 1; i < 100000; i++) { NSLog(@“%l”, i); } ! dispatch_async(dispatch_get_main_queue(),^{ //Update the UI }); } ); ! NSLog(@“After”);
  23. NSLog(@“Before”); ! dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ //Background Task ! dispatch_async(dispatch_get_main_queue(),^{

    //Update the UI }); } ); ! NSLog(@“After”);
  24. dispatch_after dispatch_once, dispatch_sync, dispatch_apply

  25. Blocks + NSOperationQueue

  26. NSOperationQueue *myQueue = [[NSOperationQueue alloc] init]; ! [myQueue addOperationWithBlock:^(void){ //Do

    something awesome }];
  27. NSOperationQueue *myQueue = [[NSOperationQueue alloc] init]; ! NSBlockOperation *operation =

    [[NSBlockOperation alloc] init]; ! [operation addExecutionBlock:^{ //Do something awesome if (!operation.isCancelled) { //Keep doing awesome stuff } }]; ! [myQueue addOperation:operation]; ! [operation cancel];
  28. NSBlockOperation *operation = [[NSBlockOperation alloc] init]; [operation addExecutionBlock:^{ //Do something

    awesome }]; ! NSBlockOperation *operation1 = [[NSBlockOperation alloc] init]; [operation1 addExecutionBlock:^{ //Do something else awesome }]; [operation1 addDependency:operation]; ! [myQueue addOperation:operation]; [myQueue addOperation:operation1];
  29. –Me “Start with GCD”

  30. Some gotchas Blocks capture in-scope variables (with the best intentions!)

  31. __block NSString *test = @“Hello!; ! void (^myBlock)() = ^(){

    test = @“Hello 2!”; }; ! myBlock(); ! NSLog(test);
  32. __block __block NSString *test = @“Hello!; ! void (^myBlock)() =

    ^(){ test = @“Hello 2!”; }; ! myBlock(); ! NSLog(test);
  33. weakself pattern self.errorHandler = ^(){ [self displayAlert:@“Oh No!”]; };

  34. weakself pattern _weak typeof(self) weakSelf = self; self.errorHandler = ^(){

    __strong typeof(weakSelf) strongSelf = weakSelf; ! if (strongSelf) { [strongSelf displayAlert:@“Oh No!”]; } }; pod ‘libextobjc’, #import "EXTScope.h"
  35. Closures in Swift

  36. {(parameterTypes) -> (returnType) in //do some awesome stuff }

  37. {(name: String) -> (Bool) in return countElements(name) > 6 }

  38. http://f*ckingclosuresyntax.com ! (or http://goshdarnclosuresyntax.com)

  39. dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { //Background Task ! dispatch_async(dispatch_get_main_queue(), { //Update

    the UI }) } )
  40. __block var test = "Hello, playground” ! var myClosure: ()

    { test = "Hello Again!" } ! myClosure ! println(test)
  41. weakself: easier self.errorHandler = { self.displayAlert(“Oh No!”) }

  42. weakself: easier self.errorHandler = { [unowned self] in self.displayAlert(“Oh No!”)

    }
  43. Further reading WWDC 2010: Introducing Blocks and Grand Central Dispatch

    on iPhone The Swift Programming Language iBook http://goshdarnblocksyntax.com http://goshdarnclosuresyntax.com