十一、内存管理中的循环引用


------ <a href="http://www.itheima.com" target="blank">Windows Phone 7手机开发</a>、<a href="http://www.itheima.com" target="blank">.Ios培训</a>、期待与您交流! -------

      首先,我们得知道什么是循环引用。循环引用就是你中有我,我中有你。例如,有A类与B类两个类,A类中有B类型的成员变量,B类中有A类型的成员变量,然后通过调用相应的setter与getter方法,来实现的引用,叫做循环引用。

     然后,我们需要知道循环引用有两种类型,一种是非ARC机制下的循环引用,一种是ARC机制下的循环引用。

一、非ARC机制下的循环引用(代码演示):

     


    main函数:

#import <Foundation/Foundation.h>
#import "House.h"
#import "Window.h"
int main()
{
    House *h = [[House alloc] init];
    Window *w = [[Window alloc] init];
    
    h.num = 110;
    w.size = 19.9;
    
    // 下面两句为循环引用的关键语句:
    h.window = w;
    w.house = h;
    
    // 在非ARC机制下,有alloc就必须有release,并且谁alloc就必须谁release
    [w release];
    [h release];
    
    return 0;
}

House类的声明与实现:

#import <Foundation/Foundation.h>

 // @class关键字的作用,是告诉编译器,某个名称是一个类
 // 此处的@class是告诉编译器,Window是该文件中的一个类
 // 并且@class是写在类的声明里面

@class Window; // 注意@class中的c不要写成大写的C,oc中的关键字是区分大小写的!!!
@interface House : NSObject


@property (nonatomic,retain) Window *window;
@property (nonatomic,assign) int num;


@end
#import "House.h"

@implementation House

- (void)dealloc // 当House类的对象被回收时,系统自动调用- dealloc方法
{

    NSLog(@"房屋号码为%d的House对象内存被回收",[self num]); // 打印用于检测House对象是否被回收
    [super dealloc]; // 在非ARC机制下,用户重写- dealloc方法时,必须在该方法最后加上[super dealloc]
}

@end
   

   Window类的声明与实现:

#import <Foundation/Foundation.h>
@class House; 

@interface Window : NSObject

@property (nonatomic,retain) House *house; // Window类中的有House类型的成员变量,该变量是oc对象
@property (nonatomic,assign) double size;

@end
#import "Window.h"

@implementation Window

- (void)dealloc // 当Window类的对象被回收时,系统自动调用- dealloc方法
{

    NSLog(@"尺寸为%.2f的Window对象内存被回收",[self size]); // 打印用于检测Window对象是否被回收
    [super dealloc]; // 在非ARC机制下,用户重写- dealloc方法时,必须在该方法最后加上[super dealloc]
}

@end
   

   程序运行结果为:不显示任何东西。 
   

   程序运行这样的结果的原因,程序在执行完后,_house以及_window这两个oc类型的成员变量,都有强指针指向,因为对象不会被回收,系统也就不会调用-dealloc方法。

    我们需要将House类声明与Window类声明中@property参数中的一端改为assign,一端保持retain不变,然后在House类的.m文件中的头文件中添加#import Window.h,同样的,在Window类的.m 文件中的头文件中添加#import House.h。最后还需要在House类的-dealloc方法中释放掉_window对象,[_window release],同样的,在Window类的-dealloc方法中释放掉_house对象。

    改后程序运行结果如下:

   

   修改后的代码,符合苹果官方的内存管理机制,“谁alloc,就谁release,一个alloc对应一个release”。


   下面来看看,如何使用苹果官方的ARC机制,将非ARC代码转换成ARC代码。

   1.选择xcode上端工具栏里面的Edit,选择Edit里面的Refactor,再选择Convert Object-C ARC,勾选需要转换的项目。

    

  2.点击check,然后点击next,会出现预览,就说是ARC代码与非ARC代码的预览

    

      3.最后点击save,选择enable,即可将非ARC代码转换成ARC代码。

   注意:转换成ARC代码后,将无法转会成非ARC代码,若需要保留非ARC代码,应该先备份一份非ARC代码。

 

总结:

        ARC代码与非ARC代码总体来的区别就是不需要用户调用release或者是autorelease来进行内存空间的释放,系统会自动释放内存空间。同时在ARC代码中,所有的@property中的oc对象中的retain全部变为strong,oc对象中的的assign全部变为weak。strong 代表强指针,一般用户默认创建的指针都为强指针,有强指针指向的对象不会被回收,weak代表弱指针,在需要创建的指针前面写上__weak则代表该指针为弱指针,若一个对象没有被强指针指向,只有被弱指针指向,那么这个对象会被回收。还有,ARC代码中的-dealloc方法里面,不再允许这样调用[super dealloc]。注意:并不是所有项目都可以使用ARC机制,某些第3方框架,不支持ARC机制,这时我们需要关闭部分文件的ARC机制。我们在Build Phases 里面选择comple source,然后再相应的.m文件后,输入-fno-objc-arc,这样即可关闭某个文件的ARC机制。同样,我们可以输入-f-objc-arc来打开某个文件的ARC机制。

   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值