您的位置:首页 > 其它

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

2015-03-15 10:21 267 查看
------ <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机制。

   
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: