《Objective-C 高级编程》读书笔记
##前言
命令行编译objc文件
1 2 3 4 5 6 7 8
| clang -fobjc-arc test.m -o test # 编译简单的oc文件,启用arc clang -fobjc-arc -S test.m # 将test.m转成汇编 test.s clang -fobjc-arc -framework Foundation test.m -o test # 编译 链接Foundation.framework clang -rewrite-objc test.m # 将 oc源码转换成cpp源码
clang -fobjc-arc -arch arm64 test.m # 将test.m转成arm64汇编test.s # 编译iPhone arm64版本 clang -fobjc-arc -framework Foundation test.m -o test -arch arm64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.2.sdk
|
Block 本质
block可以类比函数指针,但是OC利用结构体的辅助来实现,该结构体开头为isa指针,所以可以用Object的方式管理。
以一个最简单的block.m文件为例
1 2 3 4 5 6 7 8
| void test() { void (^blk)(void) = ^{ printf("hello block\n"); }; blk(); }
|
使用 clang -rewrite-objc block.m 将其转换为cpp,再查看block.cpp文件末尾内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| struct __test_block_impl_0 { struct __block_impl impl; struct __test_block_desc_0* Desc; __test_block_impl_0(void *fp, struct __test_block_desc_0 *desc, int flags=0) { impl.isa = &_NSConcreteStackBlock; impl.Flags = flags; impl.FuncPtr = fp; Desc = desc; } };
static void __test_block_func_0(struct __test_block_impl_0 *__cself) {
printf("hello block\n"); }
static struct __test_block_desc_0 { size_t reserved; size_t Block_size; } __test_block_desc_0_DATA = { 0, sizeof(struct __test_block_impl_0)};
void test() { void (*blk)(void) = ((void (*)()) &__test_block_impl_0((void *)__test_block_func_0, &__test_block_desc_0_DATA));
((void (*)(__block_impl *)) ((__block_impl *)blk)->FuncPtr)((__block_impl *)blk); }
struct __block_impl { void *isa; int Flags; int Reserved; void *FuncPtr; };
|
分析该文件:首先blk被声明为了函数指针,指向的是强制转换的 __test_block_impl_0 引用。
__test_block_impl_0 的第一个成员为 __block_impl ,而__block_impl 的第一个成员又是 isa,所以最终整个__test_block_impl_0 其实是一个OC对象,可以直接NSLog输出NSLog(@"blk = %@", blk); 处理,打印结果blk = <__NSGlobalBlock__: 0x100004150>。