ブロック問題
開発ではblockをよく使いますが、まず簡単な基本的な使い方を見てみましょう.
int main(int argc,const char * argv[]) {
@autoreleasepool {
test4();
}
return 0;
}
blockは実際には構造体を指すポインタであり、使用可能である.
clang -rewrite-objc main.mはmain.mをmainに変換する.cppファイル
main関数でtest 1を呼び出し、main.mをmainに変換する.cpp後、cppファイルにtest 1関数が表示されます.
このことからblockに保存されているのは構造体を指すポインタであり,この構造体にはblock種のコードが入った関数が保存されていることがわかる.
void test1()
{
int a = 10;
void (^block)() = ^{
NSLog(@"%d", a);
};
a = 20;
block(); // 10
}
void test2()
{
__block int a = 10;
void (^block)() = ^{
NSLog(@"%d", a);
};
a = 20;
block(); // 20
}
void test3()
{
static int a = 10;
void (^block)() = ^{
NSLog(@" %d", a);
};
a = 20;
block(); // 20
}
// a
int a = 10;
void test4()
{
void (^block)() = ^{
NSLog(@"a is %d", a);
};
a = 20;
block();// 20
}
main
int main(int argc,const char * argv[]) {
@autoreleasepool {
test4();
}
return 0;
}
blockは実際には構造体を指すポインタであり、使用可能である.
clang -rewrite-objc main.mはmain.mをmainに変換する.cppファイル
main関数でtest 1を呼び出し、main.mをmainに変換する.cpp後、cppファイルにtest 1関数が表示されます.
void test1()
{
int a = 10;
//_test1_block_impl_0 c++ , , C++ block , __test1_block_func_0
void (*block)() = ((void (*)())&__test1_block_impl_0((void *)__test1_block_func_0, &__test1_block_desc_0_DATA, a)); block a , block 10
a = 20;
//3. block FuncPtr
((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);
}
<pre name="code" class="cpp">struct __test1_block_impl_0 {
struct __block_impl impl;
struct __test1_block_desc_0* Desc;
int a;
// 2.__test1_block_impl_0 , FuncPtr
__test1_block_impl_0(void *fp, struct __test1_block_desc_0 *desc, int _a, int flags=0) : a(_a) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
block ,
static void __test1_block_func_0(struct __test1_block_impl_0 *__cself) {
int a = __cself->a; // bound by copy
NSLog((NSString *)&__NSConstantStringImpl__var_folders_36_fw4zn5v15w10psb207f993_c0000gn_T_main_f13c04_mi_0, a);
}
このことからblockに保存されているのは構造体を指すポインタであり,この構造体にはblock種のコードが入った関数が保存されていることがわかる.
在main.m中调用test2 转换为main.cpp文件后:
void test2() { __attribute__((__blocks__(byref))) __Block_byref_a_0 a = {(void*)0,(__Block_byref_a_0 *)&a, 0, sizeof(__Block_byref_a_0), 10}; // __test2_block_impl_0 a , block a , block void (*block)() = ((void (*)())&__test2_block_impl_0((void *)__test2_block_func_0, &__test2_block_desc_0_DATA, (__Block_byref_a_0 *)&a, 570425344)); (a.__forwarding->a) = 20; ((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block); }
同じ理屈だm
で呼び出すtest 3をmainに変換する.cppファイルの後:void test3() { static int a = 10; // __test3_block_impl_0 a , block a , block > void (*block)() = ((void (*)())&__test3_block_impl_0((void *)__test3_block_func_0, &__test3_block_desc_0_DATA, &a)); a = 20; ((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block); }
同じ理屈だmで呼び出すtest 4をmainに変換する.cppファイルの後:int a = 10;//<span style="color:#ff0000;"> </span> struct __test4_block_impl_0 { struct __block_impl impl; struct __test4_block_desc_0* Desc; __test4_block_impl_0(void *fp, struct __test4_block_desc_0 *desc, int flags=0) { impl.isa = &_NSConcreteStackBlock; impl.Flags = flags; impl.FuncPtr = fp; Desc = desc; } }; static void __test4_block_func_0(struct __test4_block_impl_0 *__cself) { // a </span> NSLog((NSString *)&__NSConstantStringImpl__var_folders_36_fw4zn5v15w10psb207f993_c0000gn_T_main_6730fe_mi_0, a); } static struct __test4_block_desc_0 { size_t reserved; size_t Block_size; } __test4_block_desc_0_DATA = { 0, sizeof(struct __test4_block_impl_0)}; void test4() { void (*block)() = ((void (*)())&__test4_block_impl_0((void *)__test4_block_func_0, &__test4_block_desc_0_DATA)); a = 20; ((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block); }