iOS复习笔记8:autorelease详解



一 概念
iOS在程序在运行的过程中,会创建很多个释放池,自动释放池以栈的形式存放的(先进后出)。
对象调用autorelease时,会被放入栈顶的自动释放池中。
当自动释放池销毁时,会对池的所有对象发送一次release消息;
所以发送autorelease之后引用计数不会立即-1。
autorelease返回对象本身。


二 实例
// Person.h


@interface Person


@property(nonatomic, assign) int age;


@end

// Person.m
#improt <Foundation/Foundation.h>


@implementation Person


- (void)dealloc()
{	
	NSLog(@"Person dealloc");
	[super dealloc];
}


@end

// main.m
#improt <Foundation/Foundation.h>
#improt "Person.h"


int main()
{
	@autorelease
	{// 创建了一个自动释放池
		Person* person1 = [[[Person alloc] init] autorelease];
		person1.age = 25;
	}// 释放池销毁,这一行之后会打印出:"Person dealloc"
		


	// 释放池个数不限
	@autorelease
	{
		Person* person2 = [[[Person alloc] init] autorelease];
		person2.age = 25;


		// 释放池可以嵌套
		@autorelease
		{
			Person* person3 = [[[Person alloc] init] autorelease];
			person3.age = 25;
		}
	}


	// 另一种创建方式
	NSAutoreleasePool* p = [[NSAutoreleasePool alloc] init];// 创建了一个自动释放池
	Person* person4 = [[[Person alloc] init] autorelease];
	person4.age = 25;
	[pool release];// 释放池销毁


	return 0;
}


可见释放池有两种创建方式:
方式一
@autorelease{
// 释放池内对象
}

方式二

NSAutoreleasePool* p = [[NSAutoreleasePool alloc] init];// 创建了一个自动释放池
// 释放池内对象
[pool release];




三 优缺点:
1 优点
不用再关心调用是否放在release之前;
不用关心release是否再所有调用之后。


2 缺点:
不能精确控制对象释放时间;


因此,占用内存较小的对象推荐使用autorelease


四 常见错误
1 多次调用autorelease
Person* person2 = [[[Person alloc] init] autorelease];
[person2 autorelease];
或者
Person* person2 = [[[[Person alloc] init] autorelease] autorelease];

2 调用autorelease之后调用release
Person* person2 = [[[Person alloc] init] autorelease];
[person2 release];


五 类方法自动释放优化

// Person.h


@interface Person


@property(nonatomic, assign) int age;


+ (id)person;
+ (id)personWithAge:(int)age;


@end

// Person.m
#improt <Foundation/Foundation.h>


@implementation Person


// 快速返回一个自动释放的对象
+ (id)person
{
	retur [Person alloc] init] autorelease];
}


+ (id)personWithAge:(int)age
{
	Person* p = [Person alloc] init] autorelease];
	p.age = age
	retur p;
}

@end

// main.m
#improt <Foundation/Foundation.h>
#improt "Person.h"


int main()
{
	@autorelease{
		Person* p1 = [Person person];
		p1.age = 22;
		Person* p1 = [Person personWithAge:25];


		// 类似的系统方法
		NSString* str = [NSString stringWithFormat("%d to string",2)];
		NSNumber* n = [NSNumber numberWithInt:100];
	}


	retur 0;
}



六 类方法的优化
1 问题示例
从新定义一个类Student继承自Person
// Student.h
@interface Student:Person
@property(nonatomic, assign) int grade;
@end

// Student.m
#improt <Foundation/Foundation.h>


@implementation Student
@end


然后按照下面的方法调用
// main.m
#improt <Foundation/Foundation.h>
#improt "Person.h"


int main()
{
	@autorelease{
		Student* s = [Student personWithAge:10];
		s.grade = 1;// 报错
	}


	retur 0;
}


可以看到在s.grade = 1;的地方报错:
[Person setGrade]:unrecognized selector sent to instance...
为什么呢?因为Student的personWithAge是继承自父类Person,返回的是一个Person对象,
而Person对象是没有grade属性的。


2 解决方法
修改父类Person中的类方法,将Person改为self,返回调用类的对象。


+ (id)person
{
	// 改为self后返回调用者的实例
	retur [self alloc] init] autorelease];
}


+ (id)personWithAge:(int)age
{
	Person* p = [self alloc] init] autorelease];
	// 设置父类(Person)的age值
	p.age = age
	retur p;
}


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。