黑马程序员-内存管理之autorelease和ARC机制

一.autorelease

  之前我们都是手动release对象,但是有时候我们需要延迟release对象,这里我们就需要用到autorelease,系统会把当前对象放在当前的autorelease pool中,当autorelease pool销毁时,会把当前池子中的所有对象做一次release操作。对于每一个Runloop, 系统会隐式创建一个Autorelease pool,这些池子都是以栈结构的形式存在,在每一个Runloop结束时,当前栈顶的池子会被销毁,所有对象做一次release操作

1.autorelease的基本用法
1> 会将对象放到一个自动释放池中
2> 当自动释放池被销毁时,会对池子里面的所有对象做一次release操作
3> 会返回对象本身
4> 调用完autorelease方法后,对象的计数器不变

2.autorelease的好处
1> 不用再关心对象释放的时间
2> 不用再关心什么时候调用release

3.autorelease的使用注意
1> 占用内存较大的对象不要随便使用autorelease
2> 占用内存较小的对象使用autorelease,没有太大影响


4.错误写法
1> alloc之后调用了autorelease,又调用release
@autoreleasepool
{
// 1
Person *p = [[[Person alloc] init] autorelease];

// 0
[p release];
}

2> 连续调用多次autorelease
@autoreleasepool
{
Person *p = [[[[Person alloc] init] autorelease] autorelease];
}

5.自动释放池
1> 在iOS程序运行过程中,会创建无数个池子。这些池子都是以栈结构存在(先进后出)
2> 当一个对象调用autorelease方法时,会将这个对象放到栈顶的释放池


6.自动释放池的创建方式
1> iOS 5.0前
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

[pool release]; // [pool drain];

2> iOS 5.0 开始
@autoreleasepool
{

}
下面是示例代码:

 1 #import <Foundation/Foundation.h>
 2 
 3 @interface Person : NSObject
 4 @property (nonatomic, assign) int age;
 5 
 6 + (id)person;
 7 
 8 + (id)personWithAge:(int)age;
 9 
10 @end
 1 #import "Person.h"
 2 
 3 @implementation Person
 4 
 5 + (id)person
 6 {
 7     return [[[self alloc] init] autorelease];
 8 }
 9 
10 + (id)personWithAge:(int)age
11 {
12     Person *p = [self person];
13     p.age = age;
14     return p;
15 }
16 
17 - (void)dealloc
18 {
19     NSLog(@"%d岁的人被销毁了", _age);
20     
21     [super dealloc];
22 }
23 @end
1 #import "Person.h"
2 
3 @interface GoodPerson : Person
4 
5 @property (nonatomic, assign) int money;
6 
7 @end
#import "GoodPerson.h"

@implementation GoodPerson

@end
 1 #import <Foundation/Foundation.h>
 2 #import "Person.h"
 3 #import "GoodPerson.h"
 4 
 5 int main()
 6 {
 7     @autoreleasepool {
 8         Person *p = [Person personWithAge:100];
 9         
10         
11         GoodPerson *p2 = [GoodPerson personWithAge:10];
12         
13         p2.money = 100;
14     }
15     return 0;
16 }

注意问题:

1.系统自带的方法里面没有包含alloc、new、copy,说明返回的对象都是autorelease的,例如以下2个例子。

NSString *str = @"123123";
NSString *str2 = [NSString stringWithFormat:@"age is %d", 10];


下面调用了对象方法,需要release操作
NSNumber *num = [[NSNumber alloc] initWithInt:10];

[num release];

2.开发中经常会提供一些类方法,快速创建一个已经autorelease过的对象
1> 创建对象时不要直接用类名,一般用self
+ (id)person
{
  return [[[self alloc] init] autorelease];
}

二.ARC机制

ARC机制是IOS5所引入的,英文全称Automatic Reference Counting,自动引用计数,即ARC。有了ARC我们就不需要来手动操作内存管理的引用计数了,像retain,relesase,autorelease关键字都禁止使用。ARC全程帮我们管理内存,少了很多代码,也不用担心内存泄露。

ARC的特点:

1.ARC特点
1> 不允许调用release、retain、retainCount、autorelease
2> 允许重写dealloc,但是不允许调用[super dealloc]
3> @property的参数
* strong :成员变量是强指针(适用于OC对象类型)
* weak :成员变量是弱指针(适用于OC对象类型)
* assign : 适用于非OC对象类型
4> 以前的retain改为用strong

2.ARC的判断准则:只要没有强指针指向对象,就会释放对象。

下面代码是不使用ARC和使用ARC的区别。

创建一个Person类。

非ARC

 1 #import <Foundation/Foundation.h>
 2 
 3 @class Dog;
 4 
 5 @interface Person : NSObject
 6 
 7 @property (nonatomic, retain) Dog *dog;
 8 
 9 @property (nonatomic, retain) NSString *name;
10 
11 @property (nonatomic, assign) int age;
12 
13 @end
 1 #import "Person.h"
 2 
 3 @implementation Person
 4 
 5 - (void)dealloc
 6 {
 7     NSLog(@"Person is dealloc");
 8 
 9     [_dog release];
10     [_name release];
11     
12     [super dealloc];
13 }
14 
15 @end
 1 #import <Foundation/Foundation.h>
 2 #import "Person.h"
 3 #import "Dog.h"
 4 
 5 int main()
 6 {
 7     Dog *d = [[Dog alloc] init];
 8     Person *p = [[Person alloc] init];
 9     p.dog = d;
10     [p release];
11     [d release];
12     
13     return 0;
14 }

 

使用ARC后代码变成了如下:

 1 #import <Foundation/Foundation.h>
 2 
 3 @class Dog;
 4 
 5 @interface Person : NSObject
 6 
 7 @property (nonatomic, strong) Dog *dog;
 8 
 9 @property (nonatomic, strong) NSString *name;
10 
11 @property (nonatomic, assign) int age;
12 
13 @end
 1 #import "Person.h"
 2 
 3 @implementation Person
 4 
 5 // 如果要重写dealloc,禁止写最后的[super dealloc];
 6 - (void)dealloc
 7 {
 8     NSLog(@"Person is dealloc");
 9     
10     // [super dealloc];
11 }
12 
13 @end
 1 #import <Foundation/Foundation.h>
 2 #import "Person.h"
 3 #import "Dog.h"
 4 
 5 int main()
 6 {
 7     Dog *d = [[Dog alloc] init];
 8     Person *p = [[Person alloc] init];
 9     p.dog = d;
10 
11     return 0;
12 }

很明显的变化就是使用了ARC机制后禁止调用release、retain、retainCount、autorelease关键字,原来的retain用strong来代替,重写dealloc方法时禁止调用[super dealloc]

 

posted on 2014-10-04 16:37  himym2005  阅读(222)  评论(0编辑  收藏  举报

导航