来回顾下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来修饰的值吧。
好了总结告一段落!
感谢百度,谷歌,还有前人们