Reading — step 1 of 4
Learn
~1 min readBlocks and Errors
Blocks are Objective-C's closures — anonymous functions you can pass around.
Syntax: ^returnType (args) { body }. Often inferred:
// Type: int (^)(int)
int (^square)(int) = ^(int n) {
return n * n;
};
NSLog(@"%d", square(5)); // 25
The caret ^ marks both the type and the literal.
Capturing variables — blocks close over local scope, copying by value:
int base = 100;
int (^add)(int) = ^(int n) {
return n + base; // base is captured
};
base = 200; // doesn't affect the block (already captured)
NSLog(@"%d", add(5)); // 105 — block sees base=100
For mutable captures, use __block:
__block int counter = 0;
void (^increment)(void) = ^{ counter++; };
increment();
increment();
NSLog(@"%d", counter); // 2 — counter is shared
Common use cases:
- Iteration callbacks:
[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { ... }] - Completion handlers:
[downloader fetchWithCompletion:^(NSData *data, NSError *err) { ... }] - Sorting:
[array sortedArrayUsingComparator:^NSComparisonResult(id a, id b) { ... }]
Memory caveats — blocks are objects. ARC manages them, but capturing self strongly inside an instance method's block can create retain cycles:
// Cycle: self -> block -> self
[self.api fetch:^(id result) { self.value = result; }];
// Fix with weak reference:
__weak typeof(self) weakSelf = self;
[self.api fetch:^(id result) { weakSelf.value = result; }];
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…