黑马程序员_OC学习之内存管理

来源:互联网 发布:live2d mac有哪些 编辑:程序博客网 时间:2024/05/18 20:12
---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------


前言:OC中凡是手动建立的对象都需要我们自己管理内存,这些对象被分配到堆中。每个对象都有自己的引用计数器,如果计数器变为0,那么对象就被销毁,下面是OC中一系列关于内存方面的知识总结。


一、内存管理:

关于内存方面有几个关键词:1、retain、copy:使对象引用计数器加一;

2、release:释放一次,引用计数器减一;

3、alloc:创建新对象,默认引用技术器为一;

4、dealloc方法:当对象消亡时,会调用该方法。

例如:

<span style="font-size:18px;">#import <Foundation/Foundation.h>@interface Person : NSObject@end@implementation Person- (void)dealloc {    NSLog(@"Person dead");  //当对象消亡,会调用这个方法        [super dealloc];}@endint main() {        Person *p = [[Person alloc]init];   //这时p这个指针指向的对象默认引用计数器+1;    [p retain]; //p指向的对象引用计数器+1        [p release];    //计数器-1    [p release];    //当p指向的对象计数器为0时,对象消亡;            return 0;    }</span>


----------------------------------------------------------------------------------------------------------------------------------------------------------

二、@property参数:


先看一段代码:


<span style="font-size:18px;">#import <Foundation/Foundation.h>@interface Dog : NSObject@end@interface Person : NSObject{    Dog *_dog;}- (void)setDog:(Dog *)dog;@end@implementation Person- (void)dealloc {        [_dog release]; //当人死亡时,把狗也杀了(太不道德了。。)    NSLog(@"Person dead");  //当对象消亡,会调用这个方法        [super dealloc];}- (void)setDog:(Dog *)dog {        if (dog != _dog) {  //如果这条狗不是新领养的那一条                [_dog release]; //对原来那条释放                _dog = [dog retain];    //再对新狗保留所有权            }}@end@implementation Dog- (void)dealloc {    NSLog(@"Dog dead");        [super dealloc];}@endint main() {        Person *p = [[Person alloc]init];   //这时p这个指针指向的对象默认引用计数器+1;    Dog *d1 = [[Dog alloc]init];    Dog *d2 = [[Dog alloc]init];        p.dog = d1; //当人第一次养狗时,需要retain一下,意味获取狗的所有权。        p.dog = d2; //人换了一条狗,那么就需要对原来那条狗释放        [d2 release];    [d1 release];    [p release];    //当p指向的对象计数器为0时,对象消亡;            return 0;    }</span>


根据例子我们知道,为了程序的严谨,我们会在set方法中加入一些代码,防止内存泄露。为了节省时间,可以为@property添加几个参数:


1、set方法内存管理相关的参数

retain:release旧值,retain新值(适用于OC对象类型)

assign:直接赋值(默认。适用于非OC对象类型)

copy:release旧值,copy新值


2、是否生成set方法

readwrite:同时生成setter和getter的声明、实现

readonly:只会生成getter的声明、实现


3、多线程管理

nonatomic:无原子操作,性能高

atomic:原子操作,保证数据正确,性能低(默认)


4、setter和getter方法的名称

setter:决定了set方法的名称,一定要有冒号:

getter:决定了get方法的名称(一般用在BOOL类型)


5、ARC补充(在下面做介绍)

strong:强指针,替换retain

weak:弱指针,相当于assign,但用于OC对象


例如:


<span style="font-size:18px;">#import <Foundation/Foundation.h>@interface Dog : NSObject@end@interface Person : NSObject@property (nonatomic, retain) Dog *dog; //会自动生成上面例子中setter的代码@end@implementation Person- (void)dealloc {        [_dog release]; //当人死亡时,把狗也杀了(太不道德了。。)    NSLog(@"Person dead");  //当对象消亡,会调用这个方法        [super dealloc];}@end@implementation Dog- (void)dealloc {    NSLog(@"Dog dead");        [super dealloc];}@endint main() {        Person *p = [[Person alloc]init];    Dog *d1 = [[Dog alloc]init];    Dog *d2 = [[Dog alloc]init];        p.dog = d1;        p.dog = d2;        [d2 release];    [d1 release];    [p release];            return 0;    }</span>


----------------------------------------------------------------------------------------------------------------------------------------------------------


三、循环引用:


当两个对象A包含B,B包含A时会引发循环引用,谁也不会被销毁,这时我们需要对其中一个做assign,另一个做retain


例如:


<span style="font-size:18px;">#import <Foundation/Foundation.h>@class Person;   //提前声明,告诉Dog,这个Person其实是一个类@interface Dog : NSObject@property (nonatomic,assign) Person *person;@end@interface Person : NSObject@property (nonatomic, retain) Dog *dog; //会自动生成上面例子中setter的代码@end@implementation Person- (void)dealloc {        [_dog release]; //当人死亡时,把狗也杀了(太不道德了。。)    NSLog(@"Person dead");  //当对象消亡,会调用这个方法        [super dealloc];}@end@implementation Dog- (void)dealloc {        NSLog(@"Dog dead");        [super dealloc];}@endint main() {        Person *p = [[Person alloc]init];    Dog *d = [[Dog alloc]init];        p.dog = d;    d.person = p;        [d release];    [p release];            return 0;    }</span>


----------------------------------------------------------------------------------------------------------------------------------------------------------


四、autorelease:


OC会在程序运行时创建若干个自动释放池,并把它们放到一个栈中,我们可以把一个对象放到其中,当用在对象后加上autorelease时,代表它会把该对象放到栈顶的池子中。随着一个自动释放池被销毁,它会将它里面的对象做一次release操作。


例如:


<span style="font-size:18px;">#import <Foundation/Foundation.h>@class Person;   //提前声明,告诉Dog,这个Person其实是一个类@interface Dog : NSObject@property (nonatomic,assign) Person *person;@end@interface Person : NSObject@property (nonatomic, retain) Dog *dog; //会自动生成上面例子中setter的代码@end@implementation Person- (void)dealloc {        [_dog release]; //当人死亡时,把狗也杀了(太不道德了。。)    NSLog(@"Person dead");  //当对象消亡,会调用这个方法        [super dealloc];}@end@implementation Dog- (void)dealloc {        NSLog(@"Dog dead");        [super dealloc];}@endint main() {        @autoreleasepool {                Person *p = [[[Person alloc]init]autorelease];        Dog *d = [[[Dog alloc]init]autorelease];                p.dog = d;        d.person = p;    }   //当池子被销毁,里面的对象会做一次release操作    //    [d release];  //不需要release,因为我们d与p两个对象都在自动释放池中//    [p release];            return 0;    }</span>

注意:当我们想准确操作一个对象的“生死”时,不要把它放到自动释放池中,它只适用于小数据的自动释放。


----------------------------------------------------------------------------------------------------------------------------------------------------------


五、ARC机制:(Automatic Reference Counting)


ARC属于编译时的机制,它会检查一个对象是否有强指针指向它,如果没有,它会在后面加上release代码。这点区分于JAVA的垃圾回收机制,JAVA程序会在程序运行时检测一个对象是否有指针指向,如果没有那么就会将对象作为垃圾回收。


解释一下@property中两个参数:


1、strong:声明对象为强指针(默认)


2、weak:声明对象为弱指针,当它指向的一个对象,同时没有其他强指针指向时,会被ARC添加release代码,该对象会被回收,这个弱指针也会自动被赋值为nil,所以弱指针不能单独指向对象。


例如:


<span style="font-size:18px;">#import <Foundation/Foundation.h>@class Person;   //提前声明,告诉Dog,这个Person其实是一个类@interface Dog : NSObject@property (nonatomic,strong) Person *person;    //retain变为strong@end@interface Person : NSObject@property (nonatomic, weak) Dog *dog; //防止循环引用,assign变成weak@end@implementation Person- (void)dealloc {        NSLog(@"Person dead");}@end@implementation Dog- (void)dealloc {        NSLog(@"Dog dead");//    [super dealloc ];   //这句会被报错}@endint main() {                Person *p = [[[Person alloc]init]autorelease];    Dog *d = [[[Dog alloc]init]autorelease];        p.dog = d;    d.person = p;    //    [p release];    //有了ARC,所有关于内存方面的关键字都不会再被使用。//    [d release];        return 0;    }</span>

---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------详细请查看:www.itheima.com
0 0
原创粉丝点击