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;
}

时间: 2024-10-28 08:18:29

iOS复习笔记8:autorelease详解的相关文章

iOS复习笔记6:property详解

@property type xxx 可以自动生成一个type _xxx;成员变量: 同时还生成对应的setter和getter方法. 可以通过以下四种类型的参数,控制生成getter和setter方法. 1 set方法内存管理参数 1.1 assign: 默认值,直接赋值,使用于基础数据类型 1.2 retain: release旧值,retain新值,再赋值 1.3 copy  : release旧值,copy新值 2 是否要生成setter方法的参数 2.1 readwrite: 默认值,

IOS 学习笔记 —— UILable 使用详解(一)

1 设置字体大小 //修改字体 //    NSLog(@"fontFamily = %@", self.labelTradePrice.font.familyName);     self.labelText.font = [UIFont fontWithName:@".Helvetica Neue Interface" size:13];

IOS 学习笔记 —— tableView 使用详解(一)

1 去除分割线 //去除分割线 self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; 2 高度设置 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {     UITableViewCell *cell = [self tableView:tableView cellForRo

IOS开发学习笔记(1)-----UILabel 详解

1. [代码][C/C++]代码     //创建uilabelUILabel *label1 = [[UILabel alloc] initWithFrame:CGRectMake(20, 40, 280, 80)];//设置背景色label1.backgroundColor = [UIColor grayColor];//设置taglabel1.tag = 91;//设置标签文本label1.text = @"Hello world!";//设置标签文本字体和字体大小label1.

IOS开发学习笔记(2)-----UIButton 详解

1. [代码][C/C++]代码     //这里创建一个圆角矩形的按钮    UIButton *button1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];    //    能够定义的button类型有以下6种,//    typedef enum {//        UIButtonTypeCustom = 0,          自定义风格//        UIButtonTypeRoundedRect,        

Objective-C - autorelease详解

autorelease详解 /* 1.autorelease的基本用法 1> 会将对象放到一个自动释放池中 2> 当自动释放池被销毁时,会对池子里面的所有对象做一次release操作 3> 会返回对象本身 4> 调用完autorelease方法后,对象的计数器不变 2.autorelease的好处 1> 不用再关心对象释放的时间 2> 不用再关心什么时候调用release 3.autorelease的使用注意 1> 占用内存较大的对象不要随便使用autorelea

【iOS开发必收藏】详解iOS应用程序内使用IAP/StoreKit付费、沙盒(SandBox)测试、创建测试账号流程!【2012-12-11日更新获取”产品付费数量等于0的问题”】

转的别人的 看到很多童鞋问到,为什么每次都返回数量等于0?? 其实有童鞋已经找到原因了,原因是你在 ItunesConnect 里的 “Contracts, Tax, and Banking”没有完成设置账户信息. 确定 ItunesConnect 里 “Contracts, Tax, and Banking”的状态,如下图所示,即可: 这里也是由于Himi疏忽的原因没有说明,这里先给童鞋们带来的麻烦,致以歉意. //——2012-6-25日更新iap恢复 看到很多童鞋说让Himi讲解如何恢复i

iOS中UIWebView的使用详解

iOS中UIWebView的使用详解 一.初始化与三种加载方式 UIWebView继承与UIView,因此,其初始化方法和一般的view一样,通过alloc和init进行初始化,其加载数据的方式有三种: 第一种: - (void)loadRequest:(NSURLRequest *)request; 这是加载网页最常用的一种方式,通过一个网页URL来进行加载,这个URL可以是远程的也可以是本地的,例如我加载百度的主页:     UIWebView * view = [[UIWebView al

iOS网络编程(六) NSURLSession详解

昨夜浏览Demo的时候,看到别人请求网络数据用的是NSURLSession,当时就在想这里什么,怎么没有用过,引起了我的好奇心,遂去百度-谷歌-官方文档一一查看,有了一定的了解,原来NSURLSession是iOS7中新的网络接口,它与咱们熟悉的NSURLConnection是并列的. 查找资料,写了一个小Demo,大家可以看看,有什么不足的地方,可以留言帮我指出来. // // HMTRootViewController.m // // // Created by HMT on 14-6-7.