OC学习篇之—循环引用问题

OC学习篇 尼古拉斯.赵四 9509℃ 0评论

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

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

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

来看一个具体的例子:

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中,垃圾回收器也会遇到这样的问题,所以就不采用引用计数法去管理对象了,而是另外的一种方式去管理,可以参考:点击进入

 

关注微信公众号,最新技术实时推送

转载请注明:尼古拉斯.赵四 » OC学习篇之—循环引用问题

喜欢 (0)or分享 (0)
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址