block變量捕獲
在講解block變量的捕獲之前,我們先來看看OC中的變量大致分為哪幾類:
- 局部變量
- 自動變量
- 靜態(tài)變量
- 全局變量
我們在main函數(shù)內(nèi)創(chuàng)建一個auto變量age和一個static變量height,main函數(shù)外創(chuàng)建一個全局變量weight,代碼如下:
// 全局變量
int weight = 30;
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
// 自動變量,默認省略了`auto`關鍵字
int age = 10;
// 靜態(tài)變量
static int height = 20;
void (^block)(void) = ^() {
NSLog(@"%d", age); // 10
NSLog(@"%d", height); // 200
NSLog(@"%d", weight); // 300
};
age = 100;
height = 200;
weight = 300;
block();
}
return 0;
}
我們執(zhí)行命令,將main.m轉換為c++代碼
int main(int argc, const char * argv[]) {
/* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool;
int age = 10;
static int height = 20;
void (*block)(void) = &__main_block_impl_0(
__main_block_func_0,
&__main_block_desc_0_DATA,
age,
// 可以看到height這里是將變量的內(nèi)存地址作為參數(shù)傳遞
&height
);
age = 100;
height = 200;
weight = 300;
block->FuncPtr(block);
}
return 0;
}
block結構體對象:
// 全局變量
int weight = 30;
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
// auto變量
int age;
// static變量
int *height;
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int _age, int *_height, int flags=0) : age(_age), height(_height) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
我們在創(chuàng)建一個Person類驗證變量的捕獲,代碼如下:
@interface Person : NSObject
@property (nonatomic, copy) NSString *name;
- (void)test;
@end
@implementation Person
- (void)test {
void (^block)(void) = ^{
// 注意:block內(nèi)雖然沒有寫self,但是_name等價于 self->_name
NSLog(@"--%@", _name); // 111
};
block();
}
@end
我們修改下main函數(shù)代碼如下:
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
Person *person = [[Person alloc] init];
person.name = @"111";
[person test];
}
return 0;
}
然后我們將Person.m文件轉換為c++代碼如下:
test函數(shù):
/**
這里我們發(fā)現(xiàn)test函數(shù)默認有兩個參數(shù)`self`和_cmd,這兩個參數(shù)是函數(shù)的默認隱式參數(shù)。
self:調用當前函數(shù)的對象
_cmd:函數(shù)名
*/
static void _I_Person_test(Person * self, SEL _cmd) {
void (*block)(void) = &__Person__test_block_impl_0(
__Person__test_block_func_0,
&__Person__test_block_desc_0_DATA,
self,
570425344
);
block->FuncPtr(block);
}
__Person__test_block_impl_0block結構體:
struct __Person__test_block_impl_0 {
struct __block_impl impl;
struct __Person__test_block_desc_0* Desc;
// 將當前Person對象self捕獲到block結構體內(nèi)
Person *self;
__Person__test_block_impl_0(void *fp, struct __Person__test_block_desc_0 *desc, Person *_self, int flags=0) : self(_self) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
從上面轉換的底層c++代碼分析,我們可以得出結論入下圖所示:

image
講解示例Demo地址:https://github.com/guangqiang-liu/06.1-BlockDemo1
更多文章
- ReactNative開源項目OneM(1200+star):https://github.com/guangqiang-liu/OneM:歡迎小伙伴們 star
- iOS組件化開發(fā)實戰(zhàn)項目(500+star):https://github.com/guangqiang-liu/iOS-Component-Pro:歡迎小伙伴們 star
- 簡書主頁:包含多篇iOS和RN開發(fā)相關的技術文章http://www.itdecent.cn/u/023338566ca5 歡迎小伙伴們:多多關注,點贊
- ReactNative QQ技術交流群(2000人):620792950 歡迎小伙伴進群交流學習
- iOS QQ技術交流群:678441305 歡迎小伙伴進群交流學習