在xib上removeFromSuperview引用计数问题

1,268 阅读2分钟

今天小伙伴在群里讨论view在xib上removeFromSuperview之后会不会被释放产生了歧义

注:imageView是IBOutlet,ARC下是weak,MRC下强制要写成strong

在ARC模式下

    //打印结果     retainCount     3
    NSLog(@" retainCount     %ld", CFGetRetainCount((__bridge CFTypeRef)self.ImageView));
    
    [self.ImageView removeFromSuperview];

    //打印结果    removeFromSuperview   retainCount     3
    NSLog(@" removeFromSuperview   retainCount     %ld", CFGetRetainCount((__bridge CFTypeRef)self.ImageView));
    
    [self.ImageView removeFromSuperview];
    
    //打印结果    removeFromSuperview22222222   retainCount     4(打印结果不准确)
    NSLog(@" removeFromSuperview22222222   retainCount     %ld", CFGetRetainCount((__bridge CFTypeRef)self.ImageView));
    
    [self.view addSubview:self.ImageView];
    
    //打印结果    addSubview   retainCount     5
    NSLog(@" addSubview   retainCount     %ld", CFGetRetainCount((__bridge CFTypeRef)self.ImageView));
 
    
    [self.view addSubview:self.ImageView];

    //打印结果    addSubview2222222   retainCount     5
    NSLog(@" addSubview2222222   retainCount     %ld", CFGetRetainCount((__bridge CFTypeRef)self.ImageView));

图为打印结果:

打印结果

执行removeFromSuperview方法后,会从父视图中移除,并且将Superview对视图的强引用删除,此时如果没有其他地方再对视图进行强引用,则会从内存中移除。如果还存在其他强引用,视图只是不在屏幕中显示,并没有将该视图从内存中移除。所以如果需要使用该视图,不需要再次创建,而是直接addSubview就可以了。

切换MRC模式:项目—>project—>build Setting—>搜Automatic Reference

对象销毁的标志:retainCount是否为0,只有release 才会造成引用计数-1 所以在MRC模式下,在项目不崩溃的情况下最多使用几次release,那么当时的引用计数就为几(因为引用计数有时候不准确,所以只能这样了~~~)

当视图存在的时候removeFromSuperview 不会使引用计数+1
当视图不存在的时候removeFromSuperview 引用计数不准确

打印结果 removeFromSuperview22222222 retainCount 4(打印结果不准确)

在MRC中,根据官方API的说明:

If the view’s superview is not nil, the superview releases the view.

也就是每执行一次removeFromSuperview方法,方法内部都会执行一次release操作。但是经过我的测试,发现调用removeFromSuperview方法后,引用计数并没有减少,反而增加了一个。 所以我们就可以在MRC下使用[self.imageView release]查看一下

我们之前看到的引用计数的增加,是因为系统的隐藏操作导致的。之前在MRC时期经常发现retainCount不准确,这主要是因为iOS系统API的引用、或自动释放池导致的,所以retainCount并不能当做可靠的参考。

所以,如果调用多个release,还是会崩溃的,始终要相信iOS的MRC内存管理原则,这才是可靠的。可以多次调用removeFromSuperview方法,在已经移除父视图后,其他多余的调用不会改变任何引用计数。 对于addSubview:方法也是一样的

当视图不存在的时候addSubview 会使引用计数+1
当视图存在的时候addSubview 不会使引用计数+1

参考链接 博主比我思路清晰可以参考他的这篇文章