zoukankan      html  css  js  c++  java
  • 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







  • 相关阅读:
    Leetcode Binary Tree Preorder Traversal
    Leetcode Minimum Depth of Binary Tree
    Leetcode 148. Sort List
    Leetcode 61. Rotate List
    Leetcode 86. Partition List
    Leetcode 21. Merge Two Sorted Lists
    Leetcode 143. Reorder List
    J2EE项目应用开发过程中的易错点
    JNDI初认识
    奔腾的代码
  • 原文地址:https://www.cnblogs.com/roccheung/p/5797288.html
Copyright © 2011-2022 走看看