bolck

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 */
};
  • isa 指针, 所有对象都有改指针,用于实现对象相关的功能。
  • flags,用于按bit位表示一下block的附加信息。
  • reserved,保留变量。
  • invoke,函数指针,指向具体的block实现的函数调用地址。
  • descriptor,表示该block的附加描述信息,主要是size大小,以及copy和dispose函数指针。
  • variables,capture过来的变量,block能够访问它外部的局部变量,就是因为将这些变量(活变量的地址)复制到了结构体中。

block使用局部变量的时候,可以访问,但是不可以修改变量的值。如果是访问指针类型,会修改指针所指地址的内容,不会修改指针。如果需要在block内部对局部变量做修改,使用关键字__block。被__block修饰的变量称作block变量。基本类型的block变量等效于全局变量或静态变量。

关于block的循环引用的问题:

循环引用是指两个对象互相强引用对方,即retain了对方,从而导致两个对象都无法释放而导致内存泄漏。block中的循环引用问题,是因为block在考呗到堆上的时候,会retain其引用的外部变量,那么如果block中引用了他的宿主对象,那很有可能引起循环引用。而解决的办法就是使用__weak或者__unsafe_unretained来修饰,例如

 1 typedef void(^MyBlock)(void);
 2 @interface MyViewController : UIViewController
 3
 4 @property(nonatomic, assign)MyBlock myBlock;
 5
 6 @end
 7
 8
 9
10 @implementation MyViewController
11
12 - (void)viewDidLoad{
13     [super viewDidLoad];
14
15     //系统警告:capturing ‘self‘ strongly in this block is likely to lead to retain cycle,直接导致循环引用
16     self.myBlock = ^{
17         [self func];
18     };
19
20     //不会引起循环引用
21     __weak typeof(self) weakSelf = self;
22     self.myBlock = ^{
23         [weakSelf doSth];
24     };
25     self.myBlock();
26 }
27
28 - (void)func{
29     NSLog(@"doSomething");
30 }
31
32 @end

但是在不会引起循环引用的block实现中,会存在一个问题,这个得从__weak说起。

弱引用为什么不引起循环引用?就是因为弱引用是不加引用计数,这样会产生一定的风险,其引用的对象随时有可能被ARC释放掉。为了解决这个问题,而引入的一个解决方法是:weak-strong dance。代码如下

__weak typeof(self) weakSelf = self;
self.block = ^{
    //加入强引用
    __strong typeof(weakSelf) strongSelf = weakSelf;
    [strongSelf doSth];
};

这样加入强引用,可以避免self在执行block的时候被析构而无法执行。

现在再来看一个问题,如果在添加强引用之前weakSelf已经为nil了,那强引用出来也是nil,再去执行方法同样会出问题,那为了保证方法能正确执行,Apple官方文档建议为:

__weak typeof(self) weakSelf = self;
self.block = ^{
    __strong typeof(weakSelf) strongSelf = weakSelf;
    //如果强引用self不为空才执行
    if (strongSelf) {
        [strongSelf doSth];
    }
};

这就是weak-strong dance的合理做法。

关于__unsafe_unretained, 文档中是这么写的:

In some cases you can use __unsafe_unretained if the class isn’t __weak compatible. This can, however, become impractical for nontrivial cycles because it can be hard or impossible to validate that the __unsafe_unretained pointer is still valid and still points to the same object in question.

意思是:在某些情况下,如果类不支持__weak,可以使用__unsafe_unretained,然而它在实际中仍然无法解决non-trivial cycles问题,因为它很难甚至不可能来保持__unsafe_unretained指针活跃并且仍然指向同一个对象。

官方文档传送门:

https://developer.apple.com/library/mac/releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html#//apple_ref/doc/uid/TP40011226-CH1-SW4

时间: 2024-08-29 02:22:18

bolck的相关文章

Block

OC语言BLOCK和协议 一.BOLCK (一)简介 BLOCK是什么?苹果推荐的类型,效率高,在运行中保存代码.用来封装和保存代码,有点像函数,BLOCK可以在任何时候执行. BOLCK和函数的相似性:(1)可以保存代码(2)有返回值(3)有形参(4)调用方式一样. 标识符 ^ (二)基本使用 (1)定义BLOCK变量 Int (^SumBlock)(int,int);//有参数,返回值类型为int Void (^MyBlock)()://无参数,返回值类型为空 (2)利用block封装代码

GameMap地图初始化

init_map(res_path) 1.初始化mapbase的基本信息 pos2d screen_area = {1000, 600}; //普通屏幕大小 m_spBase->init(screen_area.x / 3, screen_area.y / 3 , //屏幕划分成3*3格子 header.map_size_item.base_size.x, header.map_size_item.base_size.y ); //map格子单位大小 初始化了mapbase里面的map格子的大小

关于hadoop处理大量小文件情况的解决方法

小文件是指那些size比HDFS的block size(默认64m)小的多的文件.任何一个文件,目录和bolck,在HDFS中都会被表示为一个object存储在namenode的内存中,每一个object占用150bytes的内存空间.所以,如果有10milion个文件,每一个文件对应一个block,那么就会消耗namenode 3G来保存这些block的信息.如果规模再大一点,那么将会超出现阶段计算机硬件所能满足的极限. 控制小文件的方法有: 1应用程序自己控制 2archieve 第一种是我

OC语言BLOCK和协议

一.BOLCK (一)简介 BLOCK是什么?苹果推荐的类型,效率高,在运行中保存代码.用来封装和保存代码,有点像函数,BLOCK可以在任何时候执行. BOLCK和函数的相似性:(1)可以保存代码(2)有返回值(3)有形参(4)调用方式一样. 标识符 ^ (二)基本使用 (1)定义BLOCK变量 int (^SumBlock)(int, int); // 有参数,返回值类型为int void (^MyBlock)():// 无参数,返回值类型为空 (2)利用block封装代码 (3)Block访

Runtime -----那些被忽略的技能

        有人说现在的程序员都被惯坏了,尤其使用一些面向对象的语言开发的时候,只是简单的调用一些系统封装好的接口或者是调用一些“便利的”第三方,对于一个程序的真正实现有了解吗???又有多少了解呢???就单单的拿Objective-c 来说,确实感觉它无所不能,神马都可以做!大到整个工程文件的整合,内存的自动管理,小到图层动画的应用,界面的切换,使用几个函数就能完成,然而它的内部实现,具体如何管理的就不是那么清晰明了了.所以有时候感觉自己能用动画实现很炫酷的效果,然而主要的还是对函数的使用,

黑马程序员-------Objective-C基础4

------ android培训.java培训.期待与您交流! ---------- 1.强指针:默认的情况下所有的指针都是强指针,关键字__strong 弱指针:__week关键字修饰的指针 2.ARC:编译器将自动在代码合适的地方插入retain.release.autorelease ARC的判断准则,只要没有强指针指向对象,对象就会被释放 3.判断是否是ARC 查看项目信息:不能使用retain.release.autorelease.retainCount,在dealloc方法中不能使

Java误区: 静态代码块,当把类将被载入到自己主动运行?

JAVA静态代码块会在类被载入时自己主动运行? 非常多Java开发人员的思想,被这个思想深深的轮奸了n遍,传播这个错误思想的博客,在网上一堆,越来越多的人被轮奸. 如:http://blog.csdn.net/leeyu35/article/details/7755304 那么我们程序来证明这句话是错误的: class MyClass1 { static {//静态块 System.out.println("static block "); } } public class Main

css常用效果总结

css有不少常用的效果,你在平时浏览网站的时候可能会看到,但是真的要自己写的时候,有时候会突然忘记,今天稍微对那些常见的效果做一下小结. 1.每逢大的灾难的时候,很多网站变成了灰色,如何让网站快速变灰?css代码是很简单的,用的是css的filter功能. 代码如下: html { filter: grayscale(100%);//IE浏览器 -webkit-filter: grayscale(100%);//谷歌浏览器 -moz-filter: grayscale(100%);//火狐 -m

block和protocol

一.Block 1.基本概念 BLOCK是什么?苹果推荐的类型,效率高,在运行中保存代码.用来封装和保存代码,有点像函数,BLOCK可以在任何时候执行. BOLCK和函数的相似性:(1)可以保存代码(2)有返回值(3)有形参(4)调用方式一样. 标识符为^ // 用一个block输出n条横线 void (^lineBlock)(int) = ^(int n) { for (int i = 0; i<n; i++) { NSLog(@"----------------"); } }