block的循环引用分析

简介: block的循环引用分析

一.对下图分析



image.png

block机制:block 会把block里面的代码块的所有强指针都强引用

self:强指针

self:间接引用block

处理办法:在block模块里面写入

**定义一个weakSelf,self 的弱指针 **

typeof:自动识别参数类型

__weak typeof(self) weakSelf = self;

注意:

1.如果你的内存学的不好就在block模块里面少用self,容易造成循环引用

2.block尽量少使用下划线(_)直接访问成员属性,因为底层就是self.属性名

验证方式:(看看有没有打印)

/**
 *  如果一个对象,即将被销毁的时候,就会被调用
 */
-(void)dealloc
{
   NSLog(@"%s",__func__);
}

二.举例

循环引用指两个对象相互强引用了对方,即retain了对方,从而导致谁也释放不了谁的内存泄露问题。如声明一个delegate时一般用assign而不能用retain或strong,因为你一旦那么做了,很大可能引起循环引用。在以往的项目中,我几次用动态内存检查发现了循环引用导致的内存泄露。
 这里讲的是block的循环引用问题,因为block在拷贝到堆上的时候,会retain其引用的外部变量,那么如果block中如果引用了他的宿主对象,那很有可能引起循环引用,如:
- (void)dealloc
{
   NSLog(@"no cycle retain");
}
- (id)init
{
   self = [super init];
   if (self) {
#if TestCycleRetainCase1
    //会循环引用
    self.myblock = ^{
        [self doSomething];
    };
#elif TestCycleRetainCase2
    //会循环引用
    __block TestCycleRetain *weakSelf = self;
    self.myblock = ^{
        [weakSelf doSomething];
    };
#elif TestCycleRetainCase3
    //不会循环引用
    __weak TestCycleRetain *weakSelf = self;
    self.myblock = ^{
        [weakSelf doSomething];
    };
#elif TestCycleRetainCase4
    //不会循环引用
    __unsafe_unretained TestCycleRetain *weakSelf = self;
    self.myblock = ^{
        [weakSelf doSomething];
    };
#endif
    NSLog(@"myblock is %@", self.myblock);
}
return self;
}
- (void)doSomething
{
   NSLog(@"do Something");
}
int main(int argc, char *argv[]) {
@autoreleasepool {
    TestCycleRetain* obj = [[TestCycleRetain alloc] init];
    obj = nil;
    return 0;
 }
}

经过上面的ARC环境测试发现,在加了__weak和__unsafe_unretained的变量引入后,TestCycleRetain方法可以正常执行dealloc方法,而不转换和用__block转换的变量都会引起循环引用。


但是实际情况是:


1)MRC情况下,用__block可以消除循环引用。

2)ARC情况下,必须用弱引用才可以解决循环引用问题,iOS 5之后可以直接使用__weak,之前则只能使用__unsafe_unretained了,__unsafe_unretained缺点是指针释放后自己不会置空。


示例代码:(关于使用block会防止循环引用的代码示例)


1)在ARC下,由于__block抓取的变量一样会被Block retain,所以必须用弱引用才可以解决循环引用问题,iOS 5之后可以直接使用__weak,之前则只能使用__unsafe_unretained了,__unsafe_unretained缺点是指针释放后自己不会置空。示例代码:

//iOS 5之前可以用__unsafe_unretained
//__unsafe_unretained typeof(self) weakSelf = self;
__weak typeof(self) weakSelf = self;
self.myBlock = ^(int paramInt)
{
    //使用weakSelf访问self成员
    [weakSelf anotherFunc];
};

2)在非ARC下,显然无法使用弱引用,这里就可以直接使用__block来修饰变量,它不会被Block所retain的,参考代码:

//非ARC
__block typeof(self) weakSelf = self;
self.myBlock = ^(int paramInt)
{
     //使用weakSelf访问self成员
     [weakSelf anotherFunc];
 };


目录
相关文章
|
8月前
|
存储 Oracle Java
Java11--ZGC--权衡--ZGC--GC术语--着色指针--多重映射--读屏障标记--重定位
Java11--ZGC--权衡--ZGC--GC术语--着色指针--多重映射--读屏障标记--重定位
140 0
|
7月前
|
算法 Java 程序员
Python内存管理用引用计数(对象的`ob_refcnt`)跟踪对象,但循环引用(如A->B->A)可导致内存泄漏。
【6月更文挑战第20天】Python内存管理用引用计数(对象的`ob_refcnt`)跟踪对象,但循环引用(如A->B->A)可导致内存泄漏。为解决此问题,Python使用`gc`模块检测并清理循环引用,可通过`gc.collect()`手动回收。此外,Python结合标记清除和分代回收策略,针对不同生命周期的对象优化垃圾回收效率,确保内存有效释放。
52 3
|
存储 缓存 iOS开发
(转)谈weak对象、对象缓存以及Tagged Pointer
(转)谈weak对象、对象缓存以及Tagged Pointer
64 0
|
缓存 算法 Java
如何判断对象是否该被回收(引用计数法、可达性分析算法)
概述 垃圾收集器需要完那些内存需要回收? 什么时候回收? 如何回收?
111 0
如何判断对象是否该被回收(引用计数法、可达性分析算法)
内存中的栈(stack)、堆(heap)和静态区(static area)的用法
通常我们定义一个基本数据类型的变量,一个对象的引用,还有就是函数调用的现场保存都使用内存中的栈空间;而通过new关键字和构造器创建的对象放在堆空间;程序中的字面量(literal)如直接书写的100、"hello"和常量都是放在静态区中。
1294 0
你知道block循环引用怎么解决了吗?
在使用block的时候,最需要注意的问题便是循环引用,这节主要讲解,block是如何产生的?碰到循环引用又该怎么解决。
188 0
你知道block循环引用怎么解决了吗?
关于block的本质,你懂了吗?
block应用的目的: 把将来想要执行的代码封装起来,然后在恰当的时刻再执行代码。 block本质: 1、block是封装了函数调用和函数调用环境(如:block内部要使用的参数)的OC对象。 2、block本质上也是一个OC对象,它内部也有一个isa指针(只要内部有一个isa指针,我们就可以认为他是OC对象,因为NSObject作为最基础的OC对象,第一个成员变量就是isa指针,这是OC对象的特征)。
288 0
关于block的本质,你懂了吗?
|
存储 算法 Java
JVM05_堆的概述、内存结构、复制算法、Minor|Major|Full GC、私有区域TLAB、对象分配、参数总结、逃逸分析、栈上分配、锁消除、标量替换(一)
①. 堆的概述(共享|垃圾回收) ②. 堆的内存结构 ③. 堆空间大小的设置 -Xms -Xmx ④. 新生代与老年代参数设置 NewRation SurvivorRatio
152 0
JVM05_堆的概述、内存结构、复制算法、Minor|Major|Full GC、私有区域TLAB、对象分配、参数总结、逃逸分析、栈上分配、锁消除、标量替换(一)

热门文章

最新文章