来回顾下block

block,块语句

首先这个东东有点类似于 C语言的函数指针,但是他又不是函数指针。。。

原因是,函数指针只能操作全局变量和自己函数里面的变量,而block不同,他都能操作,只要你能想办法传给他。

而这个block呢,实际上是个什么神奇的东东呢,没错,他是一个NSObject的一个派生类,任意一个block都是一个对象,他就像一个大型的工厂类,比较特殊,具体,往下看

说到block不得不说为之引进的__block,

不多说,来看看代码就能很直观的知道__block的一个功能

这种写法完全没有问题,执行这个block语句,打印a的值。

没问题,完全可以正常打印,但是如果如果你想更改a的值,那么你回发现截图中的问题:

当你使用__block之后,你可以对这个值进行修改,

输出结果

这就是__block主要的作用就是,嗯可以这么理解,在不使用的时候,是值的传递,不能修改滴,当使用之后就是引用了,可以改变值了。

当然这只是比较简单的描述,具体的情况看看这篇博文

http://blog.csdn.net/jasonblog/article/details/7756763

从这里面就可以看出block的本质和一些他的实现。

 

接着我们来看3种情况打印关于block的结果

定义

typedeflong (^myBlock)(int, int);

这个是在MRC

这个是在ARC下

关于这个第二个问题,我也不知道该怎么解释了,总之,这就是这2个的最大区别之一!另外一个区别,仔细瞅瞅,ARC下copy的结果居然是一样的。

咱们继续往下看:

根据Block在内存中的位置分为三种类型NSGlobalBlock,NSStackBlock, NSMallocBlock。

  • NSGlobalBlock:类似函数,位于text段;
  • NSStackBlock:位于栈内存,函数返回后Block将无效;
  • NSMallocBlock:位于堆内存。

为什么blk1类型是NSGlobalBlock,而blk2类型是NSStackBlock?

blk1和blk2的区别在于,blk1没有使用Block以外的任何外部变量,Block不需要建立局部变量值的快照,这使blk1与函数没有任何区别,

从blk1所在内存地址0x47d0猜测编译器把blk1放到静态区。blk2与blk1唯一不同是的使用了局部变量base,在定义(注意是定义,不是运行)blk2时,局部变量base当前值被copy到栈上,作为常量供Block使用。

额,由上面这句话我们在回到之前使用__block的情况,如果说是拷贝出来然后使用,那么我们来看看下面的代码是怎么样的结果

首先这个 第一行的输出150的结果,很好理解,100+50嘛,为什么不是250,我觉得问这个问题的就不适合来看这篇文章!

下面的是 第二行的输出270 ,这个是block输出的结果,简单不用说。

第三行是输出250,那么也就是100+100+50,,额,如此简单是不!

但是反过来想想,上面一句话不是说吧这个值copy到栈上了,然后操作的话,那么num的值在经过第二次答应之后第三次的记过不就是150么,怎么变成250了。。。

又回到上面所说的__block这个修饰,实际上是类似于c++的引用,指针是同一个,改变的一直都是那个值。

 

这样也就能彻底的区分开了__block和__weak的差别了!

另外在ARC和MRC下都是在NSStackBlock下的情况如下:

 这种情况相信结合之前别的博客里面的就很好理解了,block本来是被分配在栈区的,根据上面的那个MRC情况下的第二种可以看出,但是在ARC下也是如此的,只是arc下默认的会是__strong来修饰一个变量,估计跟它的默认帮你管理内存机制有关,

来看看这张图,很好的诠释的ARC下里面分配内存的情况:

另外这个block块里面必须要引用进来一个值,这个值是什么都行,但必须是block外面的,如果不引用或是直接打印一行语句什么的,都会是NSGlobalBlock!

 

然后就是关于block的常用方法,

说到这里常用的方法都应该知道,主要是 __block和__weak这两个的问题

前面那个连接中可以看出__block实质是在做一件事&取指向指针的指针,那么用__block修饰过的对象在传入block中的时候是不会对该对象进行计数加1的

那么在ARC下

__weak这个在ARC下才有的,用来使对象被弱引用,并在释放后置空。

__block也不会强引用对象,就引用对象方面,到底有什么区别呢?

为此我来测试了一下:

这里用到了一个特别的类,

[NSHashTable weakObjectsHashTable];在ARC下专用

设置为单例的存在,然后定义了2个vc,在其中一个里面设置2个button,

然后设定这个av为属性的时候和非属性时的各种情况,最后发现,

当av为Strong属性时,我使用__block来修饰self是会泄露的,而__weak不会

当av为实例变量时,同和strong属性

当av为局部变量时,两者效果一样。。。__strong因为他是局部变量不会被self给持有。

 

所以在ARC下使用__weak来修饰你的self吧,避免循环引用!!

因为你不可能在block里面去改变当前self的指针这个值,所以,也就是用来对应用assgin来修饰的值吧。

好了总结告一段落!

感谢百度,谷歌,还有前人们

 

 

posted @ 2014-04-30 13:42  NS的零之轨迹  阅读(347)  评论(0编辑  收藏  举报