• OC学习篇之---循环引用问题


    在之前的一片文章中,我们介绍了数组操作对象的时候引用问题以及自动释放池的概念:

    http://blog.csdn.net/jiangwei0910410003/article/details/41926183

    今天我们继续来看一下引用计数中一个痛疼的问题:循环引用

    关于循环引用的问题,这里就不做太多解释了,就是多个对象之间相互引用,形成环状。

    来看一个具体的例子:

    Dog类和Person类之间相互引用


    Dog.h

    //
    //  Dog.h
    //  29_CyclePointer
    //
    //  Created by jiangwei on 14-10-13.
    //  Copyright (c) 2014年 jiangwei. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    
    #import "Person.h"
    
    @interface Dog : NSObject
    
    //这里不用retain,如果使用retain的话,会形成循环引用
    @property(nonatomic,assign,readwrite) Person *person;
    
    - (void)dealloc;
    
    @end
    


    Dog.m

    //
    //  Dog.m
    //  29_CyclePointer
    //
    //  Created by jiangwei on 14-10-13.
    //  Copyright (c) 2014年 jiangwei. All rights reserved.
    //
    
    #import "Dog.h"
    
    @implementation Dog
    
    - (void)dealloc{
        //[_person release];
        NSLog(@"dog dealloc");
        [super dealloc];
    }
    
    @end
    
    Dog类中有一个Person类型的属性


    Person.h

    //
    //  Person.h
    //  29_CyclePointer
    //
    //  Created by jiangwei on 14-10-13.
    //  Copyright (c) 2014年 jiangwei. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    
    @class Dog;
    
    @interface Person : NSObject
    
    @property(nonatomic,retain,readwrite) Dog *dog;
    
    - (void)dealloc;
    
    @end
    

    Person.m

    //
    //  Person.m
    //  29_CyclePointer
    //
    //  Created by jiangwei on 14-10-13.
    //  Copyright (c) 2014年 jiangwei. All rights reserved.
    //
    
    #import "Person.h"
    
    #import "Dog.h"
    
    @implementation Person
    
    - (void)dealloc{
        [_dog release];
        NSLog(@"Person dealloc");
        [super dealloc];
    }
    
    @end
    
    Person类中有Dog类型的属性


    看一下测试代码

    main.m

    //
    //  main.m
    //  29_CyclePointer
    //
    //  Created by jiangwei on 14-10-13.
    //  Copyright (c) 2014年 jiangwei. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    
    #import "Dog.h"
    #import "Person.h"
    
    //循环引用
    //是一个很麻烦的一件事,完全靠经验
    int main(int argc, const char * argv[]) {
        
        Person *p = [[Person alloc] init];
        Dog *dog = [[Dog alloc] init];
        
        [p setDog:dog];//dog计数:2
        
        [dog setPerson:p];//person计数:2
        
        [p release]; //person计数:1
        [dog release];//dog计数:1
        
        //没有释放的原因是dealloc方法中没有被执行,里面的释放代码也就没执行了,dog和person各自在等待,形成环状了
        //解决版本就是切断他们之间的联系
        //@property中不使用retain,使用assgin
        
        NSLog(@"is over");
        
        return 0;
    }
    
    我们分别定义了一个Person对象和Dog对象,然后相互引用了,但是当我们调用他们的release方法的时候,这两个对象并没有被释放

    原因很简单:

    person和dog的相互引用了,当执行release方法的时候引用计数都还是1,所以就不会调用dealloc方法了

    dealloc方法中没有被执行,里面的释放代码也就没执行了,dogperson各自在等待,形成环状了


    解决的办法是:

    切断他们之间的联系

    在一方中定义属性的时候,@property中不使用retain,使用assgin

    同时在dealloc方法中不再调用release方法了

    上面的例子中,我们可以看到Dog类中就是使用assgin


    总结

    循环引用是对象销毁的时候遇到的最大的一个问题,在java中,垃圾回收器也会遇到这样的问题,所以就不采用引用计数法去管理对象了,而是另外的一种方式去管理,可以参考:http://blog.csdn.net/jiangwei0910410003/article/details/40709457







  • 相关阅读:
    Dev Express WPF GridControl 数据导出到Excel
    WPF DockLayoutManager布局后的布局重置
    几个平台视频,音频下载(批量下载)到本地的方式
    CSS 清除内外边距
    盒子模型外边距合并--塌陷问题
    log4net 配置数据库连接
    Common.Logging+log4net搭建项目日志框架
    VS2019 找不到资产文件 “xxxxobjproject.assets.json”运行NuGet包还原以生成此文件
    javascript的数组之slice()
    javascript的数组之includes()
  • 原文地址:https://www.cnblogs.com/roccheung/p/5797288.html
Copyright © 2020-2023  润新知