------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------
自动释放池(autorelease pool)
自动释放池是OC⾥里⾯面的⼀一种内存⾃自动回收机制,⼀一般可以将⼀一些临时变量添加到⾃自动释放池中,统⼀一回收释放
当⾃自动释放池销毁时,池⾥里⾯面的所有对象都会调⽤用⼀一次release⽅方法
autorelease
OC对象只需要发送⼀一条autorelease消息,就会把这个对象添加到最近的⾃自动释放池中(栈顶的释放池)
autorelease实际上只是把对release的调⽤用延迟了,对于每⼀一次autorelease,系统只是把该对象放⼊入了当前的autorelease pool中,当该pool被释放时,该pool中的所有对象会被调⽤用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
{
}
示例:
#import <Foundation/Foundation.h>
#import "Person.h"
int main()
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
Person *pp = [[[Person alloc] init] autorelease];
[pool release]; // [pool drain];
@autoreleasepool
{
// 1
Person *p = [[[[Person alloc] init] autorelease] autorelease];
// 0
// [p release];
}
return 0;
}
void test()
{
@autoreleasepool
{// { 开始代表创建了释放池
// autorelease方法会返回对象本身
// 调用完autorelease方法后,对象的计数器不变
// autorelease会将对象放到一个自动释放池中
// 当自动释放池被销毁时,会对池子里面的所有对象做一次release操作
Person *p = [[[Person alloc] init] autorelease];
p.age = 10;
@autoreleasepool
{
// 1
Person *p2 = [[[Person alloc] init] autorelease];
p2.age = 10;
}
Person *p3 = [[[Person alloc] init] autorelease];
} // } 结束代表销毁释放池
}
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property (nonatomic, assign) int age;
@end
#import "Person.h"
@implementation Person
- (void)dealloc
{
NSLog(@"Person---dealloc");
[super dealloc];
}
@end
运行结果:
autorelease的应用示例:
1.系统自带的方法里面没有包含alloc、new、copy,说明返回的对象都是autorelease的
2.开发中经常会提供一些类方法,快速创建一个已经autorelease过的对象
1> 创建对象时不要直接用类名,一般用self
+ (id)person
{
return [[[self alloc] init] autorelease];
}
#import <Foundation/Foundation.h>
#import "Person.h"
#import "GoodPerson.h"
int main()
{
@autoreleasepool {
Person *p = [Person personWithAge:100];
GoodPerson *p2 = [GoodPerson personWithAge:10];
p2.money = 100;
}
return 0;
}
void test()
{
Person *p = [[Person alloc] init];
p.age = 200;
[p release];
// 包
// Student com.mj.test
// Student com.mj.test2
// MJStudent
// SBStudent
// Next Step
@autoreleasepool
{
// Person *p2 = [Person person];
//
// p2.age = 100;
Person *p2 = [Person personWithAge:100];
// Person *p2 = [[[Person alloc] init] autorelease];
//
// p2.age = 300;
NSString *str = @"123123";
NSString *str2 = [NSString stringWithFormat:@"age is %d", 10];
NSNumber *num = [[NSNumber alloc] initWithInt:10];
[num release];
NSNumber *num2 = [NSNumber numberWithInt:100];
}
}
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property (nonatomic, assign) int age;
+ (id)person;
+ (id)personWithAge:(int)age;
@end
#import "Person.h"
@implementation Person
+ (id)person
{
return [[[self alloc] init] autorelease];
}
+ (id)personWithAge:(int)age
{
Person *p = [self person];
p.age = age;
return p;
}
- (void)dealloc
{
NSLog(@"%d岁的人被销毁了", _age);
[super dealloc];
}
@end
#import "Person.h"
@interface GoodPerson : Person
@property (nonatomic, assign) int money;
@end
#import "GoodPerson.h"
@implementation GoodPerson
@end
运行结果:
ARC
ARC,就是由编译器代码中⾃自动加⼊入了retain/release。要注意的是,ARC并不是GC,它只是⼀一种代码静态分析⼯具
从iOS 5/Mac OS X 10.7开始导⼊入,利⽤用Xcode4.2可以使⽤用该机制
优点:
不需要担⼼心烦⼈人的内存管理和内存泄露
代码的总量变少了
代码效率⾼高,由于使⽤用编译器管理引⽤用计数,减少了低效代码的可能性
缺点:
要记住新的ARC规则、关键字、特性
使⽤用⼀一些旧代码、第三⽅方代码的时候⽐比较⿇麻烦,可能要修改编译开关,XCode4.2中默认ARC是YES的状态
ARC的判断准则:只要没有强指针指向对象,就会释放对象
1.ARC特点
1> 不允许调用release、retain、retainCount
2> 允许重写dealloc,但是不允许调用[super dealloc]
3> @property的参数
* strong :成员变量是强指针(适用于OC对象类型)
* weak :成员变量是弱指针(适用于OC对象类型)
* assign : 适用于非OC对象类型
4> 以前的retain改为用strong
指针分2种:
1> 强指针:默认情况下,所有的指针都是强指针 __strong
2> 弱指针:__weak
示例:
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Dog.h"
int main()
{
Dog *d = [[Dog alloc] init];
Person *p = [[Person alloc] init];
p.dog = d;
d = nil;
NSLog(@"%@", p.dog);
return 0;
}
void test()
{
// 错误写法(没有意义的写法)
__weak Person *p = [[Person alloc] init];
NSLog(@"%@", p);
NSLog(@"------------");
}
#import <Foundation/Foundation.h>
@class Dog;
@interface Person : NSObject
@property (nonatomic, strong) Dog *dog;
@property (nonatomic, strong) NSString *name;
@property (nonatomic, assign) int age;
@end
#import "Person.h"
@implementation Person
- (void)dealloc
{
NSLog(@"Person is dealloc");
// [super dealloc];
}
@end
#import <Foundation/Foundation.h>
@interface Dog : NSObject
@end
#import "Dog.h"
@implementation Dog
- (void)dealloc
{
NSLog(@"Dog is dealloc");
}
@end
运行结果:
模型设计示例:
#import <Foundation/Foundation.h>
#import "User.h"
#import "Status.h"
int main()
{
// 新建2个用户
User *u = [[User alloc] init];
u.name = @"2B";
User *u2 = [[User alloc] init];
u2.name = @"傻B";
// 新建2条微博
Status *s = [[Status alloc] init];
s.text = @"今天天气真好!";
s.user = u;
Status *s2 = [[Status alloc] init];
s2.text = @"今天天气真的很好!";
s2.retweetStatus = s;
s2.user = u2;
return 0;
}
#import <Foundation/Foundation.h>
typedef enum {
SexMan, // 男
SexWoman // 女
} Sex;
typedef struct {
int year;
int month;
int day;
} Date;
// 姓名、微博号码、密码、头像、性别、手机、生日
@interface User : NSObject
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *account;
@property (nonatomic, strong) NSString *password;
// http://weibo.com/a.png URL
@property (nonatomic, strong) NSString *icon;
@property (nonatomic, assign) Sex sex;
@property (nonatomic, strong) NSString *phone;
@property (nonatomic, assign) Date birthday;
@end
#import "User.h"
@implementation User
@end
#import <Foundation/Foundation.h>
#import "User.h"
// 微博内容、微博配图、发送时间、微博发送人、转发的微博、被评论数、被转发数
@interface Status : NSObject
@property (nonatomic, strong) NSString *text;
@property (nonatomic, strong) NSString *icon;
// 从1970-01-01 00:00:00 开始,一共度过了多少毫秒
@property (nonatomic, assign) long time;
//@property (nonatomic) time_t time;
@property (nonatomic, strong) User *user;
@property (nonatomic, strong) Status *retweetStatus;
@property (nonatomic, assign) int commentsCount;
@property (nonatomic, assign) int retweetsCount;
@end
#import "Status.h"
@implementation Status
@end
#import <Foundation/Foundation.h>
@interface Person : NSObject
@end
#import "Person.h"
@implementation Person
- (void)test
{
[@"3424234" release];
[@"342432" retainCount];
}
@end
运行结果:
ARC-循环引用
当两端循环引用的时候,解决方案:
1> ARC
1端用strong,另1端用weak
2> 非ARC
1端用retain,另1端用assign
示例:
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Dog.h"
int main()
{
Person *p = [[Person alloc] init];
Dog *d = [[Dog alloc] init];
p.dog = d;
d.person = p;
return 0;
}
#import <Foundation/Foundation.h>
@class Dog;
@interface Person : NSObject
@property (nonatomic, strong) Dog *dog;
@end
#import "Person.h"
@implementation Person
- (void)dealloc
{
NSLog(@"Person--dealloc");
}
@end
#import <Foundation/Foundation.h>
@class Person;
@interface Dog : NSObject
@property (nonatomic, weak) Person *person;
@end
#import "Dog.h"
@implementation Dog
- (void)dealloc
{
NSLog(@"Dog--dealloc");
}
@end
运行结果: