金莎娱乐电子游戏网Block 的下结论

1,静态变量,全局变量

直白上代码吧,嘻嘻

int global_val = 1;static int static_global_val = 2;int main(int argc, char * argv[]) {static int static_val = 3;void  = ^ { global_val = 10; static_global_val = 20; static_val = 30;};NSLog(@"%d-%d-%d",global_val,static_global_val,static_val);block ();NSLog(@"%d-%d-%d",global_val,static_global_val,static_val);}

然后rewrite一下

金莎娱乐电子游戏网 1拜访全局变量

因为那些_main_block_func_0能直接待上访谈静态变量,所以可以一直访谈这几个变量的值,也可以转移,不用操心在调用那些函数的时候,全局变量访谈不到,导致错误。所以那其间在调用全局变量的时候,正是很平日的调用全局变量,未有怎么区别。

一些静态变量则传的是一个指南针进来。因为不用操心它在函数甘休时要么其余什么地点被放飞,所以能够放心的访谈那些值

 global_val = 10; static_global_val = 20; (*static_val) = 30;

转移的是这么些指针指向的值

void  = &__main_block_impl_0_main_block_func_0, &__main_block_desc_0_DATA, &static_val));

能够看到,这里传的是指针。_main_block_func_0的功效域在main函数之外,要访谈这些变量,就只可以传指针。

structBlock_descriptor {

struct __main_block_impl_0 {
    struct __block_impl impl;
    struct __main_block_desc_0 *Desc;
    const char *fmt;
    int val;
}

什么是Block?

In programming languages, a closure is a function or reference to a
function together with a referencing environment—a table storing a
reference to each of the non-local variables (also called free
variables or upvalues) of that function.

Block是多个函数(或指向函数的指针),再增多该函数试行的外界的上下文变量。也许用一句话介绍Block,带有自动变量(局地变量)的无名函数。
Block的数据结构定义如下:

struct Block_layout {
    void *isa;
    int flags;
    int reserved;
    void (*invoke)(void *, ...);
    struct Block_descriptor *descriptor;
    /* Imported variables. */
};

struct Block_descriptor {
    unsigned long int reserved;
    unsigned long int size;
    void (*copy)(void *dst, void *src);
    void (*dispose)(void *);
};

金莎娱乐电子游戏网 2

随后看一下block访谈外界变量是怎么回事,这也是大家最关切的难点。

先来看一下部分变量:

int a = 10;int b = 20;void  = ^ { NSLog(@"%d--%d",a,b);};block ();

金莎娱乐电子游戏网 3block访谈一些变量

首先在_main_block_impl_0的定义中观看,block中用到的变量被当作成员变量追加到了结构体中,

 _main_block_impl_0(void *fp, struct _main_block_desc_0 *desc, int _a, int _b, int flags=0) : a, b {impl.isa = &_NSConcreteStackBlock;impl.Flags = flags;impl.FuncPtr = fp;Desc = desc;

}在初始化的时候,也急需把a和b的值传入。

 void () = &_main_block_impl_0_main_block_func_0, &_main_block_desc_0_DATA, a, b));

此地看到,在初步化的时候,把a,b值传入来开始化贰个_main_block_impl_0结构体。这里须求专心,传入的是a和b的值,就此大家要在结构体中改动a和b是低效的。而且编写翻译会报错,借使要在block中改动里面包车型的士值。有以下二种格局

unsignedlongintsize;

// id 为objc_object结构体的指针类型
typedef struct objc_object {
    Class isa;
} *id;

// Class 为objc_class结构体的指针类型
typedef struct objc_class *Class;
struct objc_class {
    Class isa;
};

__block完结原理

#import <Foundation/Foundation.h>

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

    __block int i = 0;

    void (^myBlock)(void) = ^{
        i ++;
        NSLog(@"%d",i);
    };

    myBlock();

    return 0;
}

把上述代码应用clang调换陈哲超码

struct __Block_byref_i_0 {
  void *__isa;
__Block_byref_i_0 *__forwarding;
 int __flags;
 int __size;
 int i;
};

struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  __Block_byref_i_0 *i; // by ref
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_i_0 *_i, int flags=0) : i(_i->__forwarding) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
  __Block_byref_i_0 *i = __cself->i; // bound by ref

        (i->__forwarding->i) ++;
        NSLog((NSString *)&__NSConstantStringImpl__var_folders_45_k1d9q7c52vz50wz1683_hk9r0000gn_T_main_3b0837_mi_0,(i->__forwarding->i));
    }
static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0*src) {_Block_object_assign((void*)&dst->i, (void*)src->i, 8/*BLOCK_FIELD_IS_BYREF*/);}

static void __main_block_dispose_0(struct __main_block_impl_0*src) {_Block_object_dispose((void*)src->i, 8/*BLOCK_FIELD_IS_BYREF*/);}

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};
int main(int argc, const char * argv[]) {
    __attribute__((__blocks__(byref))) __Block_byref_i_0 i = {(void*)0,(__Block_byref_i_0 *)&i, 0, sizeof(__Block_byref_i_0), 0};

    void (*myBlock)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, (__Block_byref_i_0 *)&i, 570425344));

    ((void (*)(__block_impl *))((__block_impl *)myBlock)->FuncPtr)((__block_impl *)myBlock);

    return 0;
}

从源码我们能窥见,带有
__block的变量也被转化成了贰个结构体__Block_byref_i_0,那几个结构体有5个分子变量。第四个是isa指针,第2个是指向自己类型的__forwarding指针,第多少个是一个标志flag,第2个是它的高低,第八个是变量值,名字和变量名同名。
isa的存款和储蓄域有三种:
• _NSConcreteStackBlock 保存在栈中的block,出栈时会被灭绝
• _NSConcreteGlobalBlock 全局的静态block,不会看望任何外界变量
• _NSConcreteMallocBlock 保存在堆中的block,当援引计数为0时会被销毁
__forwarding指针这里的职能正是本着堆的Block,把本来__forwarding指针指向和谐,换来指向_NSConcreteMallocBlock上复制之后的__block自身。然后堆上的变量的__forwarding再指向友好。那样不管__block怎么复制到堆上,依旧在栈上,都得以经过(i->__forwarding->i)来拜候到变量值。

金莎娱乐电子游戏网 4

参照他事他说加以考察资料:
http://blog.devtang.com/2013/07/28/a-look-inside-blocks/
https://gold.xitu.io/post/57ccab0ba22b9d006ba26de1

然后经过后面部分代码深入分析一下block的达成

iOS中有三种block,下文仲细说NSConcreteGlobalBlock;//在大局中定义的NSConcreteStackBlock;
//在某些定义的NSConcreteMallocBlock;//分红在堆中

先从最简便易行的看起

int main(int argc, char * argv[]) {void  = ^{ NSLog;};

(通过 在极端找到那个.m文件,然后clang -rewrite-objc 代码文件名
就足以看来文件夹有个.cpp的文件,本来想变量ViewController的文书,里面用了UIKit库,编写翻译的时候总是展现找不到,于是本人编写翻译的main.m文件)

编写翻译过来是

金莎娱乐电子游戏网 5block源码

这里先来解析一下:

static void _main_block_func_0(struct _main_block_impl_0 *__cself) { NSLog((NSString *)&__NSConstantStringImpl__var_folders_yq_s_hjnhd12x79wq1ldg1jdr_w0000gn_T_main_50d1d6_mi_0);}

能够见到,这里对应大家代码中的block中的完毕,所以能够知道,block使用的佚名函数,实际上被看做贰个函数来拍卖。不过盛传的是:一个_main_block_impl_0类型的结构体,里面有三个block_impl的结构体,和二个_main_block_desc_0的结构体。跟着是他俩的构造函数。来差不离看一下那一个_main_block_impl_0结构体吧:

isa指向那些block的品类。这里表明那几个block是NSConcreteStackBlock类型的。flag是注明,可以见见,暗中同意构造为0;还应该有三个FuncPtr,也正是指向函数地址的指针。还会有贰个__main_block_desc_0的结构体,在底下能够看来那几个结构体的开端化,三个是reserverd默感觉0,一个是block_size。是这个impl的size。所以,这个_main_block_impl_0,大家能够知道为正是贰个block实例,里面包车型客车成员变量有要施行的函数的指针,和isa(和具备的oc对象一样),还恐怕有三个size。

这段日子看一下main函数里面包车型大巴始末

 void  = &__main_block_impl_0__main_block_func_0, &__main_block_desc_0_DATA));

此间进行的操作便是:起先化叁个block实例,交给咱们这么name名字变量,也便是用name那个指针指向这一个block实例,推行的时候,直接找到这一个block中的指向函数地址的指针。

透过以上方可精晓:block的真面目,便是二个对象,蕴含了贰个指向函数首地址的指针,和一些与温馨生死相依的成员变量。

dt1 = {2016,8,30};//非法

// block结构体
struct __main_block_impl_0 {
    void *isa;
    int Flags;
    int Reserved;
    void *FuncPtr;
    struct __main_block_desc_0 *Desc;
}

Block结构体分析:

  1. isa 指针,所有指标都有该指针,用于落实目的相关的效应。
  2. flags,用于按 bit 位表示一些 block 的附加音信。
  3. reserved,保留变量。
  4. invoke,函数指针,指向具体的 block 实现的函数调用地址。
  5. descriptor, 表示该 block 的增大描述音讯,首倘使 size 大小,以及
    copy 和 dispose 函数的指针。
  6. variables,capture 过来的变量,block
    能够访谈它外表的一部分变量,就是因为将那些变量(或变量的地点)复制到了结构体中。
其次种办法是给参数加__block属性
int main(int argc, char * argv[]) {__block int block_val = 3;void  = ^ { block_val = 30;};NSLog(@"%d",block_val);block ();NSLog(@"%d",block_val);NSLog(@"%@",block);

}

金莎娱乐电子游戏网 6__block参数

能够看来里面比任何多了三个那样的结构体_Block_byref_block_val_0里面有:_isa最早化为0,__forwarding;//持有该实例本人的的指针int
__flags;为0int __s__Block_byref_block_val_0ize;sizeint
block_val;//寄放那一个变量的值原本是把三个片段变量,封装成了三个结构体赋值的时候一向给那一个结构体中的这么些值赋值(block_val->__forwarding->block_val)
= 30;

故而,在拜望这些变量的时候,其实在拜见那么些结构体的那些变量。

关于_forwarding的功力请不要焦虑。

Block有二种等级次序:{NSConcreteGlobalBlock;//在大局中定义的NSConcreteStackBlock;
//在部分定义的NSConcreteMallocBlock;//分配在堆中}

安装在栈上的block,当“name那么些名字变量”效率域停止时,block变量也会屏弃。所以,iOS提供了将block结构体和_block变量,复制到堆上的法子。就算block的name变量甘休,那么堆上的block还足以三番五次访问。而那时,_block变量结构体中的_forwarding变量能够兑现,无论在堆上照旧在栈上。都足以准确访谈_block变量。能够掌握,当把_block变量复制到堆上的时候,_forwarding就对准堆里中的自个儿。所以随意访谈栈中自身,依然堆中的自身,最后访谈都是堆中的那一个值。

一个Block对_block的内部存储器管理方法与
ARC机制完全同样。而_main_block_desc 中的copy和dispose就是那些
__block的retain和release操作。

那什么样block在时候会复制到堆呢1,掉用block的copy方法,2.block看作函数再次回到值再次来到时。3,block调用外面包车型大巴_strong的id的类时,或用_block时。4,方法中,用usingblock或者GCD中的API时。

那边想讲一下,在一些函数里,定义block时,打印出来如故NSConcreteGlobalBlock类型的,并且假如用了外界变量,不管是assign依旧week依然strong类型的,打字与印刷出来都以NSConcreteMallocBlock类型的。所以小编揣摸那会不会是苹果新版的精耕细作,为了block在拜会无效的变量,直接把block拷贝到堆上,进而也拷贝一份变量。可能是本身忽略了中等的某些步骤

实际到了此地,不用再描述,也精晓为啥会发送死循环,又怎么消除了。当在block中用self的时候,block拷贝到堆上,首先,在栈上的那几个block有八个持有者,是name这么些变量。当name那一个变量成效域之外,栈上这一个block就release了。,那么当block拷贝到堆上的时候,block有二个持有者是self,那么block在拷贝时,它的变量三个self指针,也会拷贝,而self又针对那几个block,block持有self,self持有block,两个都不会释放。要打破这一个轮回,必要将self置为__week,就算拷贝多个week指针,那也不影响self的引用计数。

intval;

// OC 类声明
@interface MyObject : NSObject {
    int val0;
    int val1;
}
@end

// 该类的对象的结构体
struct MyObject {
    Class isa;
    int val0;
    int val1;
};

Blcok捕获外界变量的本来面目

测验代码

#import <Foundation/Foundation.h>

int global_i = 1;

static int static_global_j = 2;

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

    static int static_k = 3;
    int val = 4;

    void (^myBlock)(void) = ^{
        global_i ++;
        static_global_j ++;
        static_k ++;
        NSLog(@"Block中 global_i = %d,static_global_j = %d,static_k = %d,val = %d",global_i,static_global_j,static_k,val);
    };

    global_i ++;
    static_global_j ++;
    static_k ++;
    val ++;
    NSLog(@"Block外 global_i = %d,static_global_j = %d,static_k = %d,val = %d",global_i,static_global_j,static_k,val);

    myBlock();

    return 0;
}

运维结果

Block 外  global_i = 2,static_global_j = 3,static_k = 4,val = 5
Block 中  global_i = 3,static_global_j = 4,static_k = 5,val = 4

行使clang将main.m文件转变为main.cpp,代码如下

int global_i = 1;

static int static_global_j = 2;

struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  int *static_k;
  int val;
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int *_static_k, int _val, int flags=0) : static_k(_static_k), val(_val) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
  int *static_k = __cself->static_k; // bound by copy
  int val = __cself->val; // bound by copy

        global_i ++;
        static_global_j ++;
        (*static_k) ++;
        NSLog((NSString *)&__NSConstantStringImpl__var_folders_45_k1d9q7c52vz50wz1683_hk9r0000gn_T_main_6fe658_mi_0,global_i,static_global_j,(*static_k),val);
    }

static struct __main_block_desc_0 {
  size_t reserved;
  size_t Block_size;
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)};


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

    static int static_k = 3;
    int val = 4;

    void (*myBlock)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, &static_k, val));

    global_i ++;
    static_global_j ++;
    static_k ++;
    val ++;
    NSLog((NSString *)&__NSConstantStringImpl__var_folders_45_k1d9q7c52vz50wz1683_hk9r0000gn_T_main_6fe658_mi_1,global_i,static_global_j,static_k,val);

    ((void (*)(__block_impl *))((__block_impl *)myBlock)->FuncPtr)((__block_impl *)myBlock);

    return 0;
}

大局变量global_i和静态全局变量static_global_j因为是全局的,成效域广,所以能够被Block捕获并修改值。
有的变量和静态变量被Block从外侧捕获进来,在__main_block_impl_0中能够看看有些变量val和静态变量static_k,成为__main_block_impl_0以此结构构的成员变量了。

__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int *_static_k, int _val, int flags=0) : static_k(_static_k), val(_val)

在那一个构造函数中,局地变量和静态变量被抓走为成员变量追加到构造函数中。
到此,_main_block_impl_0结构体正是这么把机关变量捕获进来的。也正是说,在实行Block语法的时候,Block语法表明式所选择的自发性别变化量的值是被保留进了Block的结构体实例中,也正是Block自己中。
假若Block外面还应该有比很多有的变量,静态变量等等,那几个变量在Block里面并不会被运用到。那么这几个变量并不会被Block捕获进来,也正是说并不会在构造函数里面传播它们的值。Block捕获外部变量仅仅只捕获Block闭包里面会用到的值,别的用不到的值,它并不会去捕获。
一些变量val即便被破获进来了,可是是用
__cself->val来做客的。Block仅仅捕获了val的值,并不曾捕获val的内部存款和储蓄器地址。所以在__main_block_func_0这几个函数中纵然大家重写这一个活动变量val的值,照旧没办法去改换Block外面自动变量val的值。
小结:
局地变量是以值传递格局传递到Block的构造函数里面去的。Block只捕获Block中会用到的变量。由于只捕获了活动变量的值,并非内部存款和储蓄器地址,所以Block内部不能够更动机关变量的值。Block捕获的外界变量能够更动值的是静态变量,静态全局变量,全局变量。

先看一下Block使用的语法

宣示三个block重回值 = ^{};

 int  = ^(int a,int b){ return ;};

作为叁个函数的参数:- testBlock:(NSString *s {NSString *a = s;}[self
testBlock:^NSString * {a = 5;return @”1″;}];

myBlock = ^{ NSLog(@“ Who is Block retainer : %@ %@“,weakSelf, _obj) };

通过block使用的佚名函数,实际上被当做轻便的C语音函数来管理。即自动变量须臾间值被缴械

静态全局变量,全局变量由于效用域的因由,于是能够直接在Block里面被退换。他们也都存款和储蓄在全局区。

impl.isa = &_NSConcreteStackBlock;
fmt = "f";
val = 10;

static_k ++;

block是C语言的扩充效用。带有自动变量的佚名函数

_NSConcreteMallocBlock:有强指针援引或copy修饰的分子属性援用的block会被复制一份到堆中变为MallocBlock,未有强指针援引即销毁,生命周期由工程师调整

int main() {
    int dmy = 256;
    int val = 10;
    const char *fmt = "f";

    void (*blk)(void) = &__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA, fmt, val);
    return 0;
}

1.为防止循环引用必须进行Block;

收获自动变量值
封存该机关变量的须臾间值

}

应用进行block语法时的电动变量fmt和val来开首化__main_block_impl_0结构体实例。

Block捕捉外界变量

Block存储

名称 实质
Block 栈上Block的结构体实例
__block变量 栈上__block变量的结构体实例
存储域
NSConcreteStackBlock
NSConcreteGlobalBlock 程序的数据区
NSConcreteMallocBlock

typedef int (^blk_t)(int);
blk_t blk = ^(int count){return count};
不截获自动变量的值,放置在前后相继的数据区,其余的block放置在栈上

block跨越变量作用域可存在的原由 ?
__block变量用结构体成员变量__forwarding存在的由来 ?
配置在全局变量上的block,从变量功能域外也得以通过指针安全的施用,但设置在栈上的block,__block变量,假设其所属的变量效用域甘休,该block,__block变量就被丢弃。
将配置在栈上的block复制到堆上,那样尽管block变量的效用域结束,堆上的block还是能承袭存在。
复制到堆上的block将_NSConcreteMallocBlock类对象写入block的结构体实例的积极分子变量isa
impl.isa = &_NSConcreteMallocBlock;
__block变量用结构体成员变量__forwarding可以已毕无论__金莎娱乐电子游戏网,block变量配置在栈上照旧堆上,都能科学的访谈__block变量。在__block变量配置在堆上时,只要栈上的结构体实例成员变量__forwarding指向堆上的结构体实例。

诚如编写翻译器自行决断是不是将block从栈上copy到堆上
编写翻译器不可能张开决断的图景:向方法或函数的参数中传送block时
上面包车型客车章程或函数不用手动复制
1.Cocoa框架的不二秘籍且方法名中满含usingBlock
NSArray enumerateObjectsUsingBlock
2.CGD 的API
dispatch_async函数

- (id)getBlockArray{
    int val = 10;
    return [[NSArray alloc] initWithObjects: ^{NSLog(@"blk0:%d",val);},
                                                       ^{NSLog(@"blk1:%d",val);}, nil];
}

- (void)testBlock{
    id obj = getBlockArray();
    typedef void (^blk_t) (void);
    blk_t blk = (blk_t)[obj objectAtIndex:0];
    blk(); // 异常
}
// getBlockArray 函数执行结束时,栈上的Block已被废弃

// 修正 如果block不截取自动变量则可正确运行
- (id)getBlockArray{
    int val = 10;
    return [[NSArray alloc] initWithObjects: [^{NSLog(@"blk0:%d",val);} copy],
                                                       [^{NSLog(@"blk1:%d",val);} copy], nil];
}
block类 副本源的安排存款和储蓄域 复制效果
_NSConcreteStackBlock 从栈复制到堆
_NSConcreteGlobalBlock 前后相继的数据区 哪些也不做
_NSConcreteMallocBlock 援引计数扩展

不管block配置在哪个地方,用copy方法复制都不会挑起其余难题,在不确定期调用copy即可

}

block语法表明式中使用的机动变量被当作成员变量追加到了__main_block_impl_0结构体中

结构体成员的象征方法

在OC中,比如NSObject的class_t结构体实例,以及NSMutableArray的class_t结构体实例等,均生成并保证各种类的class_t结构体实例。该实例持有注脚的成员变量、方法的名目、方法的落到实处(即函数指针)、属性以及父类的指针。

impl.isa= &_NSConcreteStackBlock;

总的来讲,所谓‘截获自动变量的值’意味着在举办block语法时,block语法表明式所运用的自行变量值被保留到block的协会体实例中

__weak AviewController *weakSelf = self;

此__main_block_impl_0结构体相当于基于objc_objct结构体的OC类对象的结构体。
对中间的成员变量 isa 实行早先化
isa = &_NSConcreteStackBlock;
即_NSConcreteStackBlock相当于class_t结构体实例,在将block作为OC的目的管理时,关于此类的音信放置于_NSConcreteStackBlock中。所以block的本来面目就是OC的指标

struct 结构体名

__block

__block同block同样成为__Block_byref_val_o结构体类型的电动变量,即栈上变化的__Block_byref_val_0结构体实例。该变量最早化为10,且那么些值也出现在结构体的初步化中,那意味该组织体持有也等于原机关变量的积极分子变量。

__block int val = 10;
void (^blk)(void) = ^{val = 1;};

// 编译器代码
struct __Block_byref_val_0 {
    void *__isa;
    __Block_byref_val_0 * __forwarding;
    int val;
}

struct __main_block_impl_0 {
    __Block_byref_val_0 *val;
    ...
}

block的__main_block_impl_0结构体实例持有指向__block变量的__Block_byref_val_0结构体实例的指针。
__Block_byref_val_0结构体实例的积极分子变量__forwarding持有指向该实例自己的指针
另外,__block变量的__Block_byref_val_0结构体并不在Block的__main_block_impl_0结构体中。那样做是为着在多个Block中选择同样__block变量。

staticintstatic_global_j =2;

MyObject类的实例变量val0和val1被间接表明为指标的结构体成员。
各样的结构体正是基于objc_class结构体的class_t结构体

OC中,一般Block就分为以下3种,_NSConcreteStackBlock,_NSConcreteMallocBlock,_NSConcreteGlobalBlock。

__block变量存款和储蓄域

__block变量的配置存储 block从栈上复制到堆时的影响
从栈复制到堆,并被block持有
被block持有

将栈上的__block变量结构体实例复制到堆上时,会将成员变量_forwarding的值替换为复制指标堆上的__block变量结构体实例的地址

void(*invoke)(void*, …);

struct class_t {
    struct class_t *isa;
    struct class_t *superclass;
    Cache cache;
    IMP *vtable;
    uintptr_t data_NEVER_USE;
}

如下:

__forwarding指针这里的法力便是针对性堆的Block,把原先__forwarding指针指向和煦,换来指向_NSConcreteMallocBlock上复制之后的__block本身。然后堆上的变量的__forwarding再指向友好。那样不管__block怎么复制到堆上,还是在栈上,都得以因而(i->__forwarding->i)来会见到变量值。

staticintstatic_k =3;//静态变量

4.调用系统API入参中含有usingBlcok的办法

- (id)init {

static_global_j ++;

自动变量(局地变量)是以值传递情势传送到Block的构造函数里面去的。Block只捕获Block中会用到的变量。由于只捕获了活动变量的值,并内部存款和储蓄器地址,所以Block内部不可能退换机关变量的值。

staticvoid__main_block_func_0(struct__main_block_impl_0
*__cself) {

我们在看下C语言的源码:

Date dt1;

(*(结构体数组名+下标)). 结构体成员

};

__block 的实现

_NSConcreteMallocBlock是享有对象的。

int*static_k = __cself->static_k;// bound by copy

就此值也是被改成的

布局体数组名 [下标]. 结构体成员

带__block的电动变量 和 静态变量
正是一直地址访问。所以在Block里面可以直接退换变量的值。

Block 循环利用难题

void (^ myBlock)(id myObj);

static_k ++;

};

二种定义格式

__main_block_impl_0(void*fp,struct__main_block_desc_0
*desc,int*_static_k,int_val,intflags=0) : static_k(_static_k),
val(_val) {

Desc = desc;

2.从全部对象的角度上来看:

size_t Block_size;

(1)struct 结构体名 变量名

if (self = [super init]){

void(*myBlock)(void) =
((void(*)())&__main_block_impl_0((void*)__main_block_func_0,
&__main_block_desc_0_DATA, &static_k, val));

__forwarding 在栈上和堆上的功力分歧

相关文章