Blocks 是 C 語言級別的語法擴展,類似函數指針但更強大:可捕獲上下文變量,支持閉包特性。iOS 4.0+ / Mac OS X 10.6+ 支持。廣泛用於異步回調、枚舉、排序等場景。
copy/release 內存管理^ 符號// 無參無返回
void (^myBlock)(void) = ^(void) {
NSLog(@"in block");
};
myBlock(); // 調用
// 有參有返回
int (^addBlock)(int, int) = ^(int a, int b) {
return a + b;
};
int result = addBlock(10, 20); // 30
typedef int (^SumBlock)(int, int);
SumBlock mySum = ^(int a, int b) {
return a + b;
};
默認情況下 Block 捕獲外部變量的值副本。加 __block 使 Block 共享同一變量存儲,可在 Block 內修改並對外可見:
__block int sum = 0;
int (^accumulate)(int, int) = ^(int a, int b) {
sum = a + b; // 修改外部變量
return sum;
};
accumulate(20, 30); // sum 變為 50
場景:Dog 定時吠叫,Person 接收通知。傳統需定義 Protocol、設置 delegate;Blocks 方式更簡潔:
// Dog.h
@interface Dog : NSObject
@property (copy) void (^barkCallback)(Dog *dog, int count);
- (void)startBarking;
@end
// Dog.m
@implementation Dog
- (void)startBarking {
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerFire:) userInfo:nil repeats:YES];
}
- (void)timerFire:(NSTimer *)timer {
static int count = 0;
count++;
if (self.barkCallback) {
self.barkCallback(self, count); // 回調 Block
}
}
@end
// Person.m
- (void)setupDog {
Dog *dog = [[Dog alloc] init];
dog.barkCallback = ^(Dog *thisDog, int count) {
NSLog(@"Person heard dog %d bark %d times", thisDog.dogID, count);
};
[dog startBarking];
}
copy,將棧上 Block 複製到堆self 時用 __weak (ARC) 或 __block (MRC)dealloc 中釋放 Block 屬性Blocks 讓異步回調代碼更內聚,減少協議/代理樣板代碼。掌握 __block、copy、循環引用處理是高效使用的關鍵。