iOS Development with Blocks

6,657 views
6,425 views

Published on

Slides from Jeff Kelley’s MobiDevDay presentation on blocks and iOS.

Published in: Technology
0 Comments
12 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
6,657
On SlideShare
0
From Embeds
0
Number of Embeds
161
Actions
Shares
0
Downloads
208
Comments
0
Likes
12
Embeds 0
No embeds

No notes for slide
  • -Straw Poll: Who here has done iOS development before? -C development?
  • After: but that’s ugly. We can make this look better.
  • iOS Development with Blocks

    1. 1. iOS Development with Blocks <ul><li>Jeff Kelley (@jeff_r_kelley) </li></ul><ul><li>MobiDevDay Detroit | February 19, 2011 </li></ul><ul><li>Slides will be on blog.slaunchaman.com </li></ul>
    2. 2. Introduction <ul><li>Blocks </li></ul><ul><ul><li>What are blocks? </li></ul></ul><ul><ul><li>Why should we use blocks? </li></ul></ul><ul><li>Grand Central Dispatch </li></ul><ul><ul><li>How does GCD help iOS development? </li></ul></ul>
    3. 3. Blocks <ul><li>Apple extension to the C language </li></ul><ul><li>Similar to closures, lambdas, etc. </li></ul><ul><li>Encapsulate code like a function, but with extra “magic” </li></ul>
    4. 4. Your First Block <ul><li>void (^helloWorldBlock)(void) = ^ { </li></ul><ul><ul><li>printf (&quot;Hello, World!n&quot;); </li></ul></ul><ul><li>}; </li></ul>
    5. 5. Calling Your First Block <ul><li>void (^helloWorldBlock)(void) = ^ { </li></ul><ul><ul><li>printf (&quot;Hello, World!n&quot;); </li></ul></ul><ul><li>}; </li></ul><ul><li>helloWorldBlock(); </li></ul>
    6. 6. Blocks That Return <ul><li>Blocks return just like functions. </li></ul><ul><li>int (^fortyTwo)(void) = ^{ </li></ul><ul><li>return 42; </li></ul><ul><li>} </li></ul><ul><li>int a = fortyTwo(); </li></ul>
    7. 7. Blocks That Take Arguments <ul><li>Just like functions: </li></ul><ul><li>BOOL (^isFortyTwo)(int) = ^(int a) { </li></ul><ul><ul><li>return (a == 42); </li></ul></ul><ul><li>} </li></ul><ul><li>BOOL myBool = isFortyTwo(5); // NO </li></ul>
    8. 8. Blocks Capture Scope <ul><li>int a = 42; </li></ul><ul><li>void (^myBlock)(void) = ^{ </li></ul><ul><ul><li>printf(&quot;a = %dn&quot;, a); </li></ul></ul><ul><li>}; </li></ul><ul><li>myBlock(); </li></ul>
    9. 9. <ul><li>int a = 42; </li></ul><ul><li>void (^myBlock)(void) = ^{ </li></ul><ul><ul><li>a++; </li></ul></ul><ul><ul><li>printf(&quot;a = %dn&quot;, a); </li></ul></ul><ul><li>}; </li></ul><ul><li>myBlock(); </li></ul>
    10. 10. <ul><li>__block int a = 42; </li></ul><ul><li>void (^myBlock)(void) = ^{ </li></ul><ul><ul><li>a++; </li></ul></ul><ul><ul><li>printf(&quot;a = %dn&quot;, a); </li></ul></ul><ul><li>}; </li></ul><ul><li>myBlock(); </li></ul>
    11. 11. Block Typedefs <ul><li>Simple block that returns an int and takes a float: </li></ul><ul><li>typedef int (^floatToIntBlock)(float); </li></ul><ul><li>Now initialize it: </li></ul><ul><li>floatToIntBlock foo = ^(float a) { return (int)a; }; </li></ul>
    12. 12. Using Blocks as Arguments <ul><li>Method Signature: </li></ul><ul><li>- (void)doThisBlock:(void (^)(id obj))block </li></ul><ul><li>returns void, takes id argument </li></ul>
    13. 13. Block Typedefs As Arguments <ul><li>First typedef the block, then use it as an argument: </li></ul><ul><li>typedef int (^floatToIntBlock)(float); </li></ul><ul><li>void useMyBlock(floatToIntBlock foo); </li></ul>
    14. 14. Block Scope <ul><li>void (^myBlock)(void); </li></ul><ul><li>if (someValue == YES) { </li></ul><ul><ul><li>myBlock = ^{ printf(&quot;YES!n&quot;) }; </li></ul></ul><ul><li>} else { </li></ul><ul><ul><li>myBlock = ^ { printf(&quot;NO!n&quot;) }; </li></ul></ul><ul><li>} </li></ul>
    15. 15. Block Memory Management <ul><li>Block_copy() and Block_release() </li></ul><ul><li>Copied onto heap </li></ul><ul><li>Blocks are Objective-C objects! </li></ul><ul><ul><li>[myBlock copy]; </li></ul></ul><ul><ul><li>[myBlock release]; </li></ul></ul>
    16. 16. Block Memory Management <ul><li>Unlike Objective-C objects, blocks are created on the stack </li></ul><ul><li>Block_copy() moves them to the heap </li></ul><ul><li>Block_retain() does not . </li></ul><ul><li>Can also call [myBlock autorelease] </li></ul>
    17. 17. <ul><li>NSString *helloWorld = [[NSString alloc] initWithString:@&quot;Hello, World!&quot;]; </li></ul><ul><li>void (^helloBlock)(void) = ^{ </li></ul><ul><li>NSLog(@&quot;%@&quot;, helloWorld); </li></ul><ul><li>}; </li></ul><ul><li>[helloWorld release]; </li></ul><ul><li>helloBlock(); </li></ul>Blocks Retain Objects
    18. 18. What Are Blocks Good For? <ul><li>Replacing Callbacks </li></ul><ul><li>Notification Handlers </li></ul><ul><li>Enumeration </li></ul>
    19. 19. What Are Blocks Good For? <ul><li>Replacing Callbacks </li></ul><ul><li>Notification Handlers </li></ul><ul><li>Enumeration </li></ul>
    20. 20. Replacing Callbacks <ul><li>Old UIView animations: </li></ul><ul><li>[UIView beginAnimations:@&quot;foo&quot; context:nil]; </li></ul><ul><li>[UIView setAnimationDelegate:self]; </li></ul><ul><li>[UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)]; </li></ul><ul><li>Then you implement the callback </li></ul>
    21. 21. Replacing Callbacks <ul><li>- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context { </li></ul><ul><ul><li>if ([animationID isEqualToString:kIDOne]) { </li></ul></ul><ul><ul><ul><li>… </li></ul></ul></ul><ul><ul><li>} else if ([animationID isEqualToString:kIDTwo]) { </li></ul></ul><ul><ul><ul><li>… </li></ul></ul></ul><ul><ul><li>} </li></ul></ul><ul><li>} </li></ul>
    22. 22. Replacing Callbacks <ul><li>New UIView Animations: </li></ul><ul><li>[UIView animateWithDuration:0.3 animations:^{ [myView setAlpha:0.0f]; } completion:^(BOOL finished) { [self doSomething]; }]; </li></ul>
    23. 23. Replacing Callbacks <ul><li>New UIView Animations: </li></ul><ul><li>[UIView animateWithDuration:0.3 animations:^{ [myView setAlpha:0.0f]; } completion:^(BOOL finished) { [self doSomething]; }]; </li></ul>
    24. 24. Replacing Callbacks <ul><li>New UIView Animations: </li></ul><ul><li>[UIView animateWithDuration:0.3 animations:^{ [myView setAlpha:0.0f]; } completion:^(BOOL finished) { [self doSomething]; }]; </li></ul>
    25. 25. Replacing Callbacks <ul><li>New UIView Animations: </li></ul><ul><li>[UIView animateWithDuration:0.3 animations:^{ [myView setAlpha:0.0f]; } completion:^(BOOL finished) { [self doSomething]; } ]; </li></ul>
    26. 26. What Are Blocks Good For? <ul><li>Replacing Callbacks </li></ul><ul><li>Notification Handlers </li></ul><ul><li>Enumeration </li></ul>
    27. 27. Notification Handlers <ul><li>Old Notifications: </li></ul><ul><li>[notificationCenter addObserver:self selector:@selector(foo:) name:kMyNotification object:myObject]; </li></ul>
    28. 28. Notification Handlers <ul><li>Old Notifications: Userinfo Dictionaries </li></ul><ul><li>- (void)foo:(NSNotification *)aNotification { NSDictionary *userInfo = [aNotification userInfo]; NSString *UID = [userInfo objectForKey:kIDKey]; NSNumber *value = [userInfo objectForKey:kValueKey]; } </li></ul>
    29. 29. Notification Handlers <ul><li>New Notification Handlers: </li></ul><ul><li>[notificationCenter addObserverForName:kName object:myObject queue:nil usingBlock:^(NSNotification *aNotification) { [myObject doSomething]; }]; </li></ul><ul><li>[myObject startLongTask]; </li></ul>
    30. 30. What Are Blocks Good For? <ul><li>Replacing Callbacks </li></ul><ul><li>Notification Handlers </li></ul><ul><li>Enumeration </li></ul>
    31. 31. Enumeration <ul><li>Basic Enumeration </li></ul><ul><li>for (int i = 0; i < [myArray count]; i++) { </li></ul><ul><ul><li>id obj = [myArray objectAtIndex:i]; </li></ul></ul><ul><ul><li>[obj doSomething]; </li></ul></ul><ul><li>} </li></ul>
    32. 32. Enumeration <ul><li>But… </li></ul><ul><li>for (int i = 0; i < [myArray count]; i++) { id obj = [myArray objectAtIndex:i]; [obj doSomething]; for (int j = 0; j < [obj count]; j++) { // Very interesting code here. } } </li></ul>
    33. 33. Enumeration <ul><li>NSEnumerator </li></ul><ul><li>NSArray *anArray = // ... ; NSEnumerator *enumerator = [anArray objectEnumerator]; </li></ul><ul><li>id object; </li></ul><ul><li>while ((object = [enumerator nextObject])) { </li></ul><ul><li>// do something with object... </li></ul><ul><li>} </li></ul>
    34. 34. Enumeration <ul><li>Fast Enumeration (10.5+) </li></ul><ul><li>for (id obj in myArray) { </li></ul><ul><ul><li>[obj doSomething]; </li></ul></ul><ul><li>} </li></ul>
    35. 35. Enumeration <ul><li>Block-based enumeration </li></ul><ul><li>[myArray enumerateObjectsUsingBlock: </li></ul><ul><ul><li>^(id obj, NSUInteger idx, BOOL *stop) { </li></ul></ul><ul><ul><ul><li>[obj doSomething]; </li></ul></ul></ul><ul><ul><li>}]; </li></ul></ul>
    36. 36. Enumeration <ul><li>So why use block-based enumeration? </li></ul><ul><ul><li>-enumerateObjectsWithOptions:usingBlock: </li></ul></ul><ul><ul><ul><li>NSEnumerationReverse </li></ul></ul></ul><ul><ul><ul><li>NSEnumerationConcurrent </li></ul></ul></ul><ul><ul><li>Concurrent processing! And for free! </li></ul></ul>
    37. 37. What Are Blocks Good For? <ul><li>Replacing Callbacks </li></ul><ul><li>Notification Handlers </li></ul><ul><li>Enumeration </li></ul>
    38. 38. What Are Blocks Good For? <ul><li>Replacing Callbacks </li></ul><ul><li>Notification Handlers </li></ul><ul><li>Enumeration </li></ul><ul><ul><li>Sorting </li></ul></ul>
    39. 39. What Are Blocks Good For? <ul><li>Replacing Callbacks </li></ul><ul><li>Notification Handlers </li></ul><ul><li>Enumeration </li></ul><ul><ul><li>Sorting </li></ul></ul>
    40. 40. Sorting <ul><li>NSArray </li></ul><ul><ul><li>-sortedArrayWithOptions:usingComparator: </li></ul></ul><ul><ul><li>Concurrent sorting for free! </li></ul></ul>
    41. 41. Blocks Wrap-Up <ul><li>Carat Syntax </li></ul><ul><li>Block Memory Management </li></ul><ul><li>Using Blocks as Arguments </li></ul><ul><li>Replacing Callbacks, Notification Handlers, Enumeration, and Sorting </li></ul>
    42. 42. Intro to Grand Central Dispatch
    43. 43. Moore’s Law <ul><li>The quantity of transistors that can be placed inexpensively on an integrated circuit has doubled approximately every two years. The trend has continued for more than half a century and is not expected to stop until 2015 or later. </li></ul><ul><li>Wikipedia </li></ul>
    44. 44. Grand Central Dispatch (GCD) <ul><li>Open-source threading library (libdispatch) </li></ul><ul><ul><li>Apache license </li></ul></ul><ul><li>Automatically optimizes threading </li></ul><ul><li>Provides queues, timers, event handlers, etc. </li></ul>
    45. 45. Simple GCD <ul><li>dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul); </li></ul><ul><li>dispatch_async(queue, ^{ </li></ul><ul><ul><li>[self performLongTask]; </li></ul></ul><ul><li>} </li></ul>
    46. 46. Basic Dispatch Functions <ul><li>dispatch_async(queue, block); dispatch_async_f(queue, context, func); </li></ul><ul><ul><li>Schedules block or function on queue, returns immediately </li></ul></ul><ul><li>dispatch_sync(queue, block); dispatch_sync_f(queue, context, func); </li></ul><ul><ul><li>Schedules block or function on queue, blocks until completion </li></ul></ul>
    47. 47. Dispatch Queues <ul><li>dispatch_queue_t </li></ul><ul><li>Main Queue </li></ul><ul><ul><li>Analogous to main thread (Do your UI operations here) </li></ul></ul><ul><ul><li>dispatch_get_main_queue() </li></ul></ul>
    48. 48. Global Queues <ul><li>dispatch_get_global_queue(priority, flags); </li></ul><ul><ul><li>priority is one of three constants: </li></ul></ul><ul><ul><ul><li>DISPATCH_QUEUE_PRIORITY_LOW </li></ul></ul></ul><ul><ul><ul><li>DISPATCH_QUEUE_PRIORITY_NORMAL </li></ul></ul></ul><ul><ul><ul><li>DISPATCH_QUEUE_PRIORITY_HIGH </li></ul></ul></ul><ul><ul><li>secong arg should always be 0ul (for now) </li></ul></ul>
    49. 49. Making Queues <ul><li>dispatch_queue_create(label, attr) </li></ul><ul><ul><li>Use reverse DNS for label </li></ul></ul><ul><ul><ul><li>com.example.myQueue </li></ul></ul></ul><ul><ul><li>pass NULL for attr </li></ul></ul><ul><li>Be sure to use dispatch_release() </li></ul>
    50. 50. Using Queues <ul><li>Custom queues are serial </li></ul><ul><ul><li>First-in, first-out, one at a time </li></ul></ul><ul><li>Global queues are concurrent </li></ul><ul><ul><li>GCD automatically chooses how many (usually # of CPU cores) </li></ul></ul>

    ×