iOS開發——Block使用小結
Block語法看上去好像很特別,但它實際上是作為極普通的C語言源代碼處理的。Block的實質,就是Objective-C的對象。
1、Block的語法
^ 返回值類型 參數列表 表達式
可省略返回值類型:^ 參數列表 表達式。省略返回值類型時,如果表達式中有return語句就使用該返回值的類型,如果表達式中沒有return語句,就使用void類型。
再省略參數列表:^ 表達式。這個就是大家最熟知的記敘方式。
int val = 10;
void (^blk)(void) = ^{
printf("val = %d\n",val);
};
blk();
2、__block說明符
若想在Block語法的表達式中將值賦給在Block語法外聲明的自動變量,需要在該自動變量上附加__block說明符。不然就會產生編譯錯誤。
__block int val = 10;
void (^blk)(void) = ^{
val = 11;
};
blk();
printf("val = %d\n",val);
3、Block循環引用
先看看下面的源代碼吧!
typedef void(^blk_t)(void);
@interface MyObject : NSObject{
blk_t blk_;
}
@end
@implementation MyObject
- (id)init {
self = [super init];
blk_ = ^{
NSLog(@"self = %@",self);
};
return self;
}
@end
MyObject類對象的Block類型成員變量blk_持有賦值為Block的強引用。即MyObject類對象持有Block。init實例方法中執行的Block語法使用持有__strong修飾符的id類型變量self。並且由於Block語法賦值在了成員變量blk_中,因此通過Block語法生成在棧上的Block此時由棧復制到堆,並持有所使用的self。self持有Block,Block持有self。這正是循環引用。
為避免循環引用,可聲明附有__weak修飾符的變量,並將self賦值使用。
- (id)init {
self = [super init];
id __weak tmp = self;
blk_ = ^{
NSLog(@"self = %@",tmp);
};
return self;
}
iOS開發——Block使用小結