Block 与 循环引用
1、 在所有的Block中,使用self 都会引起循环引用吗?
答:不一定.循环引用的原因是相互指引,相互是关键.如果相互这一层关系达不到就没有所谓的循环引用
2、 UIView动画为什么不会引起循环引用?
答:UIView的调用的是类方法,当前控制器不可能强引用一个类 ,所以循环无法形成
3、 masory为什么不会引起循环引用?
答:UIView的调用的是类方法,当前控制器不可能强引用
4、AFN为什么不会引起循环引用?
答:不一定分情况, AFN无循环是因为绝大部分情况下,你的网络类对象是不会被当前控制器引用的,这时就不会形成引用环。
5、那么什么情况下会引起循环引用?
1、 强引用自定义的block. 里面再次调用self,导致的循环引用.
2 、循环引用的发生的条件就是强持有这个block ,并且被block里面的加入的对象强持有.
3、使用NSNotification 使用系统自带的block 会发生循环引用.如下:
[[NSNotificationCenter defaultCenter] addObserverForName:@"" object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * note) {
NSLog(@"%@",self.view);
}];
6、循环引用解决办法?
答:
1、 事前避免,我们在会产生循环引用的地方使用 weak 弱引用,以避免产生循环引用。
2、事后补救,我们明确知道会存在循环引用,但是我们在合理的位置主动断开环中的一个引用,使得对象得以回收。
block 与 内存管理
1、 block是什么数据类型?
答:block其实是一个结构体 可反编译查看cpp文件
2、 block为什么对它内部的对象默认强引用呢?
答:block会对它内部的对象强引用一次。应该是为了防止内部的对象离开对象的代码环境不至于被释放掉,还能继续使用。PS:需要注意的是,对对象的强引用不是对对象的属性等强引用
3、 Block作为类变量属性时为啥用copy修饰?堆栈存储位置是怎样的?
答:block声明之后内存是存在于栈上的,而不是存在于堆上.它本身的作用域是创建时的作用域,一旦在作用外的地方调用block将导致程序崩溃
使用retain也可以,但是 block的retain行为 默认是用copy实现的.
因为block变量默认为栈变量,为了能够在block声明的作用域外使用,所以把block拷贝到堆上去,所以说为了block属性声明和实际的操作一致,最好声明为copy.
:在Objective-C语言中,一共有3种类型的block:
1._NSConcreteGlobalBlock 全局的静态block,不会访问任何外部变量。
2._NSConcreteStackBlock 保存在栈中的block,当函数返回时会被销毁。
3._NSConcreteMallocBlock 保存在堆中的block(从栈中copy过去的),当引用计数为0时会被销毁。
Block内捕获变量会改变自身存储位置,包括读取变量和__block这种写变量,两种方式(其实结果是一样的)。
【在MRC下】:存在栈、全局、堆这三种形式。
【在ARC下】:大部分情况下系统会把Block自动copy到堆上。