Objective-C Block(2)

Block内部定义

我们想要知道Block的实现过程,首先我们深入Block,下图是对Block的结构是在栈中的结构,图片来自互联网。

下面代码为对应结构体定义:

struct Block_descriptor {
    unsigned long int reserved;
    unsigned long int size;
    void (*copy)(void *dst, void *src);
    void (*dispose)(void *);
};
struct Block_layout {
    void *isa;
    int flags;
    int reserved;
    void (*invoke)(void *, ...);
    struct Block_descriptor *descriptor;
    /* Imported variables. */
};

Block_layout就是对block结构体的定义:

  • isa指针:指向表明该block类型的类。

  • flags:按bit位表示一些block的附加信息,比如判断block类型、判断block引用计数、判断block是否需要执行辅助函数等。

  • reserved:保留变量,我的理解是表示block内部的变量数。

  • invoke:函数指针,指向具体的block实现的函数调用地址。

  • descriptor:block的附加描述信息,比如保留变量数、block的大小、进行copy或dispose的辅助函数指针。

  • variables:因为block有闭包性,所以可以访问block外部的局部变量。这些variables就是复制到结构体中的外部局部变量或变量的地址。

Block类型

从上面Block的定义Block_layout结构体中isa指针类型分为三种:

  • _NSConcreteGlobalBlock:全局的静态block,不访问任何外部变量,不会涉及到任何拷贝,比如一个空的block。例如:
^{print("hello world");}
  • _NSConcreteStackBlock:保存在栈中的block,引用周围变量,当函数返回时被销毁。
    char a = 'A';
    ^{ print("%c\n",a); }
  • _NSConcreteMallocBlock:保存在堆中的block。该类型是由栈中Block ( Block_copy / Copy ) 复制到堆中形成的。
    //只需要加上copy就可以
    char a = 'A';
    [^{ print("%c\n",a); } copy];

需要注意的是我们一般创建的Block默认都是在栈中的,而系统的基础数据类型也是在栈中,那么又能使用同一个栈,倒是元素丢失,出现野指针,我们在开发中使用安全可以在定义Block时使用copy属性迁移到栈中。

Block使用

  • 使用typedef来定义Block提高程序可读性。
//适应typedef提高可读性
typedef void (^ReturnTextBlock)(NSString *showText);

@interface nickNameViewController : UIViewController

@property (nonatomic, copy) ReturnTextBlock returnTextBlock;

- (void)returnText:(ReturnTextBlock)block;

@end
  • 使用安全我们定义Block使用copy属性
@property (nonatomic, copy) ReturnTextBlock returnTextBlock;
  • 外部变量使用__block关键字,可在Block中修改,默认不能修改
__block int age = 0;  
void (^addAge) = ^{  
   age += 1;  
}  
NSLog(%d,age ) 
  • 避免循环引用
__block int age = 0;  
__weak id weakSelf = self;
void (^push) = ^{  
   [weakSelf push];  
}  

PS

在实际开发Block的使用非常多,作为方法参数,比如网络请求的失败和成功回调,SDWebImage也同样使用多种闭包来完成对应的功能,我记得曾经用的一个插件把Selecte做成Block也是很方便,但是在使用的时候要注意。今天在博客中介绍堆和栈并非传统意义的堆栈,是程序在运行时在内存的分布情况,之后我们将详细介绍。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章