美文网首页
Block对象研究

Block对象研究

作者: zhouluyao | 来源:发表于2016-06-14 12:01 被阅读24次

研究工具:clang

创建一个名为block.c的源文件

#include <stdio.h>

int main(){

^{printf("Hello ,World!\n");}();

return 0;

}

命令行输入:clang  -rewrite-objc block.c   可在block.c所在的目录下看到一个block.cpp文件进行分析

block的主要构成

isa指针:所有对象都有该指针,用于实现对象的相关功能

invoke:函数指针,指向具体的block实现的函数指针

descriptor:标示该block的附加信息,主要是size大小,以及copy和dispose函数的指针

variables:block能够访问它外部的局部变量,就是因为这些变量(或者变量的地址)复制到了结构体中

结构体本身并不附带任何额外信息

创建block时,实际就是在方法中声明一个struct,并且初始化该struct的成员。而执行block时,就是调用那个单独的C函数,并把该struct指针传递过去。

在objc中,根据对象的定义,凡是首地址是*isa的结构体指针,都可以认为是对象(id).

常见的3种类型的block

_NSConcreteGlobalBlock,全局静态block,不会访问任何外部变量

_NSConcreteStackBlock,保存在栈中的block,block返回时被销毁

_NSConcreteMallocBlock,保存在堆中的block,引用计数为0时被销毁

只有一个block被调用copy方法的时候,系统才会将这个block复制到堆上,从而产生NSConcreteMallocBlock类型的block

局部变量在block内不能被修改

static void__main_block_func_0(struct__main_block_impl_0 *__cself) {

inti = __cself->i;// bound by copy

printf("%d",i);}

在block中引用的局部变量i,实际上是在声明block时,被复制到__main_block_impl_0结构体的那个变量,block内部修改变量i,不会影响到外部的变量i.

__block修改局部变量

struct__Block_byref_i_0 {

void*__isa;  //凡是首地址是*isa的结构体指针,都可以认为是对象(id).

__Block_byref_i_0 *__forwarding;

int __flags;

int __size;

int i;}

变量i,成了一个结构体 在__main_block_impl_0 中引用着__Block_byref_i_0 *i;// by ref 结构体指针 ,这样就起到修改外部局部变量的作用

负责结构体__Block_byref_i_0的内存管理,增加了copy和dispose函数指针,用于在调用前后修改相应变量的引用计数

static struct__main_block_desc_0 {

size_t reserved;

size_t Block_size;

void(*copy)(struct__main_block_impl_0*,struct__main_block_impl_0*);

void(*dispose)(struct__main_block_impl_0*);

} __main_block_desc_0_DATA = {0,sizeof(struct__main_block_impl_0), __main_block_copy_0, __main_block_dispose_0};

ARC对block类型的影响

int main(int argc,char* argv[]) {

@autoreleasepool{

int i =1024;

void(^block)(void) = ^{

printf("%d",i);

};

block();

NSLog(@"%@",block);

return0;}

}

非ARC运行结果//10242016-06-14 10:46:03.238 MemoryInMRC[7473:3171916] <__NSStackBlock__: 0x7fff5a58f548>

ARC运行结果//10242016-06-14 10:49:03.121 MemoryInMRC[7528:3174176] <__NSMallocBlock__: 0x7fe36a7003e0>

循环引用

self对block引用,block捕捉到self时

XYZBlockKeeper*__weakweakSelf=self;  self.block=^{   [weakSelf doSomething];//捕获到的是弱引用  }

如果捕获到的是当前对象的成员变量对象,同样也会造成对self的引用

id  tmpIvar=_ivar;//临时变量,避免了self引用   self.block=^{   [tmpIvar msg];  }

block对变量的捕获规则

静态储存区变量:全局变量、static修饰变量可以修改

block接受的参数,可以修改

__block引用,可以修改。//bound by reference 如果时id类型则不会被block retain,必须手动处理其内存管理。

局部变量不可以修改//bound by copy

相关文章

  • Block对象研究

    研究工具:clang 创建一个名为block.c的源文件 #include int main(){^{print...

  • objective-C Block对象

    block对象简介及语法 什么是block? block对象是一组指令,可以像调用函数指令那样调用block对象。...

  • iOS __block和__weak的区别

    __block 1.__block对象在block中是可以被修改、重新赋值的。2.__block对象在block中...

  • iOS __block和__weak区别

    __block对象在block中可以被修改、重新赋值 __block对象在block中不会被block强引用一次,...

  • iOS block 捕获外部变量以及注意点

    参考文章:深入研究Block捕获外部变量和__block实现原理做一些简单的总结说明: (1)对于四种非对象变量:...

  • 关于Block的一个经典bug

    之前常常遇到block的循环引用问题,就稍微研究了一下,block对于访问外部对象类型有严格的限制,通常会使用__...

  • Block 跳转页面A->B->C C->

    1,首先定义代理(定义block)。 2触发代理()触发block, 3,执行代理的对象(执行block的对象) ...

  • block概念

    block的实质: block实质是oc对闭包的对象实现,简单点来说 block就算是对象。 block的书写方式...

  • Block循环引用

    block中循环引用问题 由于block会对block中的对象进行持有操作,而如果此时block中的对象又持有了该...

  • 2018-07-10 关于weakself

    在使用block时,会出现循环引用的问题。当block对象是属于当前对象本身时,如果再在block中使用当前对象的...

网友评论

      本文标题:Block对象研究

      本文链接:https://www.haomeiwen.com/subject/jlkudttx.html