For the best viewing experience, please download this presentation and view it in Keynote. SlideShare doesn't handle the animations well.
Blocks are a powerful language feature. However, they are underused and under-appreciated in Objective-C, especially compared to Ruby. My intent is to make blocks easy to understand and show many practical uses of blocks.
4. What are blocks?
Pieces of code that can be stored and executed when
needed
Also known as lambdas, closures, anonymous
functions, first-class functions, higher-order functions
Can be passed as a parameter, returned from a
method/function, and stored in data structures
Blocks make adding new features to a language easy
5. What does “closure” mean?
Blocks store all the variables that are in scope when the
block is created
Closure makes it possible to store a block indefinitely,
then restore the context at will
Objective-C objects are automatically retained/released
C objects must be manually retained/released
8. Gotchas
Retain loops
Xcode profiler will warn you of block retain loops
Unlike regular Objective-C objects, blocks are created
on the stack
Be sure to call -copy if you need it to live beyond the
current stack frame
Make sure to de-stackify blocks before storing them
in a data structure
10. What are blocks good for?
Completion callbacks
Continuations
Multithreading
Delegate replacement
Other design pattern modifications
11. Callbacks
Most uses of blocks are some form of callback
Since blocks have closure, they can restore the caller’s
context without any effort on our part
12. Completion Blocks
Most common use of blocks in Objective-C
A callback that happens only after some task has
finished
Some operations, such as network requests take an
unknown amount of time
Core Animation also uses many completion blocks
13. Completion Blocks
Object Object
A B
Block
Object B finishes executing and calls
Object A calls Object B and
passescompletion block.
the a completion block.
14. Completion Blocks
Object Object
A B
Block
Object B finishes executing and calls
Object A calls Object B and
passescompletion block.
the a completion block.
15. Completion Blocks
Object Object
A B
Block
Object B finishes executing and calls
Object A calls Object B and
passescompletion block.
the a completion block.
16. Continuations
Think of it like a completion block wrapped in a
completion block wrapped in a completion block...
Essentially building your own runtime stack.
17. Continuations
Object Object Object
A B C
Block
Object C BAthen calls Objectand to
Object finisheswraps Object A’s
Object A calls Object needwith
So, Object B Object B B and calls
Object and executing C
block theacompletion C finishes.
knownew completion block.
passes new completion block.
theinwhen Object block.
a completion block.
18. Continuations
Object Object Object
A B C
Block
Object C BAthen calls Objectand to
Object finisheswraps Object A’s
Object A calls Object needwith
So, Object B Object B B and calls
Object and executing C
block theacompletion C finishes.
knownew completion block.
passes new completion block.
theinwhen Object block.
a completion block.
19. Continuations
Object Object Object
A B C
Block
Object C BAthen calls Objectand to
Object finisheswraps Object A’s
Object A calls Object needwith
So, Object B Object B B and calls
Object and executing C
block theacompletion C finishes.
knownew completion block.
passes new completion block.
theinwhen Object block.
a completion block.
20. Continuations
Object Object Object
A B C
Block
Object C BAthen calls Objectand to
Object finisheswraps Object A’s
Object A calls Object needwith
So, Object B Object B B and calls
Object and executing C
block theacompletion C finishes.
knownew completion block.
passes new completion block.
theinwhen Object block.
a completion block.
21. Continuations
Object Object Object
A B C
Block
Object C BAthen calls Objectand to
Object finisheswraps Object A’s
Object A calls Object needwith
So, Object B Object B B and calls
Object and executing C
block theacompletion C finishes.
knownew completion block.
passes new completion block.
theinwhen Object block.
a completion block.
22. Continuations
Object Object Object
A B C
Block
Object C BAthen calls Objectand to
Object finisheswraps Object A’s
Object A calls Object needwith
So, Object B Object B B and calls
Object and executing C
block theacompletion C finishes.
knownew completion block.
passes new completion block.
theinwhen Object block.
a completion block.
23. Multithreading: GCD
Grand Central Dispatch (GCD) makes heavy use of
blocks
Blocks are not tied to a thread until they are executed
Blocks can be queued up without blocking threads
Threads can spend more time running and less time
waiting
24. Multithreading: GCD
Code can be made asynchronous simply by
surrounding it with dispatch_async(queue, ^{ ... });
36. Block Delegation
Delegates are essentially protocols that specify a list of
method callbacks
These method callbacks can be easily replaced with
block callbacks
Rule of thumb: 3 or less delegate callbacks should be
handled using blocks.
37. Block Delegation
Advantages:
No additional protocols
No need to conform to a protocol
Easy to change block callbacks dynamically
40. Template Method
Sometimes algorithms differ by only a few lines
Those few lines can be replaced by a virtual method
Subclasses define the virtual method
41. Template Method
Let’s use blocks instead!
Advantages:
No need for subclassing
May not need a new class at all
Template can be changed dynamically
47. Builder Pattern
Some objects have complex structures that vary widely
between uses
Examples: Database tables, UITableView
A block can define the construction of an object
48. Builder Pattern
// Ruby on Rails database table construction
create_table :person do |t|
t.string :name, null: false
t.integer :age, null: false
t.float :weight
end
49. Builder Pattern
// Contrived example, but very feasible.
// Creating a custom table view form.
[RBTableView tableViewUsingBlock:^(RBTableView * t) {
[t addStringField:@“name” required:YES];
[t addIntegerField:@“age” required:YES];
[t addFloatField:@“weight” required:NO];
}];
52. Lockless Exclusion
Accessor
Solution:
Have another object handle thread-safety
Put critical code in a block
Give the block to the thread-safety handler
62. Read/Write LEA
Code that only reads from shared memory doesn’t
need exclusive access
Code that writes to shared memory needs exclusive
access
GCD barrier blocks and concurrent queues are a
perfect solution
63. Read/Write LEA
// Read-only LEA
- (void)accessSharedDataReadOnlyAsync:(void(^)(id sharedData))block {
NSParameterAssert(block);
// myQueue must be a concurrent queue!
dispatch_async([self myQueue], ^{
block([self sharedData]);
});
}
64. Read/Write LEA
// Read/write LEA
- (void)accessSharedDataReadWriteAsync:(void(^)(id sharedData))block {
NSParameterAssert(block);
// myQueue must be a concurrent queue!
dispatch_barrier_async([self myQueue], ^{
block([self sharedData]);
});
}
The practical application of blocks is language independent.\n
\n
\n
\n
\n
\n
ARC usually handles calling -copy for you.\nARC does not handle calling -copy before storing a block in a data structure.\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
Continuations are powerful enough to build many features into a language. For example, you can add exceptions to a language using continuations. \n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
I’m assuming the 2-core processor is not hyper-threaded.\n
I’m assuming the 2-core processor is not hyper-threaded.\n
I’m assuming the 2-core processor is not hyper-threaded.\n
I’m assuming the 2-core processor is not hyper-threaded.\n
I’m assuming the 2-core processor is not hyper-threaded.\n
I’m assuming the 2-core processor is not hyper-threaded.\n
I’m assuming the 2-core processor is not hyper-threaded.\n
I’m assuming the 2-core processor is not hyper-threaded.\n
I’m assuming the 2-core processor is not hyper-threaded.\n
I’m assuming the 2-core processor is not hyper-threaded.\n
I’m assuming the 2-core processor is not hyper-threaded.\n
I’m assuming the 2-core processor is not hyper-threaded.\n
I’m assuming the 2-core processor is not hyper-threaded.\n
I’m assuming the 2-core processor is not hyper-threaded.\n
I’m assuming the 2-core processor is not hyper-threaded.\n
I’m assuming the 2-core processor is not hyper-threaded.\n
I’m assuming the 2-core processor is not hyper-threaded.\n
I’m assuming the 2-core processor is not hyper-threaded.\n
I’m assuming the 2-core processor is not hyper-threaded.\n
I’m assuming the 2-core processor is not hyper-threaded.\n
I’m assuming the 2-core processor is not hyper-threaded.\n
I’m assuming the 2-core processor is not hyper-threaded.\n
I’m assuming the 2-core processor is not hyper-threaded.\n
I’m assuming the 2-core processor is not hyper-threaded.\n
I’m assuming the 2-core processor is not hyper-threaded.\n
I’m assuming the 2-core processor is not hyper-threaded.\n
I’m assuming the 2-core processor is not hyper-threaded.\n
I’m assuming the 2-core processor is not hyper-threaded.\n
I’m assuming the 2-core processor is not hyper-threaded.\n
I’m assuming the 2-core processor is not hyper-threaded.\n
I’m assuming the 2-core processor is not hyper-threaded.\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
The builder pattern is, in a way, the opposite of the template pattern. A template defines the main algorithm and the subroutines are added in via implementing virtual methods or blocks. The builder pattern defines the subroutines and the conductor method or block defines the main algorithm. \n
\n
Advantages: \nNo need to subclass UITableView (RBTableView technically).\nEasy to make custom table views.\n
\n
\n
\n
\n
“Manager” does not imply the singleton pattern. The shared data manager could be any arbitrary object. \n
“Manager” does not imply the singleton pattern. The shared data manager could be any arbitrary object. \n
“Manager” does not imply the singleton pattern. The shared data manager could be any arbitrary object. \n
“Manager” does not imply the singleton pattern. The shared data manager could be any arbitrary object. \n
“Manager” does not imply the singleton pattern. The shared data manager could be any arbitrary object. \n
“Manager” does not imply the singleton pattern. The shared data manager could be any arbitrary object. \n
“Manager” does not imply the singleton pattern. The shared data manager could be any arbitrary object. \n
“Manager” does not imply the singleton pattern. The shared data manager could be any arbitrary object. \n
“Manager” does not imply the singleton pattern. The shared data manager could be any arbitrary object. \n
“Manager” does not imply the singleton pattern. The shared data manager could be any arbitrary object. \n
“Manager” does not imply the singleton pattern. The shared data manager could be any arbitrary object. \n
“Manager” does not imply the singleton pattern. The shared data manager could be any arbitrary object. \n
“Manager” does not imply the singleton pattern. The shared data manager could be any arbitrary object. \n
“Manager” does not imply the singleton pattern. The shared data manager could be any arbitrary object. \n
“Manager” does not imply the singleton pattern. The shared data manager could be any arbitrary object. \n
“Manager” does not imply the singleton pattern. The shared data manager could be any arbitrary object. \n
“Manager” does not imply the singleton pattern. The shared data manager could be any arbitrary object. \n
“Manager” does not imply the singleton pattern. The shared data manager could be any arbitrary object. \n
“Manager” does not imply the singleton pattern. The shared data manager could be any arbitrary object. \n
“Manager” does not imply the singleton pattern. The shared data manager could be any arbitrary object. \n
“Manager” does not imply the singleton pattern. The shared data manager could be any arbitrary object. \n