------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
@implementation Person
// 当一个Person对象被回收的时候,就会自动调用这个方法
- (void)dealloc
{
NSLog(@"Person对象被回收");
// super的dealloc一定要调用,而且放在最后面
[super dealloc];
}
@end
1、内存管理原则
1)谁创建,谁释放。如果你通过alloc、new或(mutable)copy来创建一个对象,那么你必须调用release或autorelease。换句话说,不是你创建的,就不用你去释放
2)一般来说,除了alloc、new或copy之外的方法创建的对象都被声明了autorelease
3)谁retain,谁release。只要你调用了retain,无论这个对象是如何生成的,你都要调用release
示例:
int main()
{
//计数器为 1
Person *p = [[Person alloc] init];
//NSUInteger c = [p retainCount];
//NSLog(@"计数器:%ld", c);
// 计数器为2 retain方法返回的是对象本身
[p retain];
//计数器为 1
[p release];
// 计数器为0 野指针:指向僵尸对象(不可用内存)的指针
[p release];
return 0;
}
2、@property参数
1)、默认格式@property(参数1,参数2)类型名字
@interface Person : NSObject
@property int age;
// retain : 生成的set方法里面,release旧值,retain新值
@property (retain) Book *book;
@property (retain) NSString *name;
@end
2)默认参数为atomic,即提供多线程安全
//对象类型的成员变量
@property (nonatomic, strong) Person *p;
//一般数据类型
@property (nonatomic, assign) int age;
3、循环引用
解决方法:B和C互相引用时,应该一端使用ratain,另一端使用assign
2、两种方式的区别
1)#import方式会包含被引用类的所有信息,包括被引用类的变量和方法;
2)@class方式只是告诉编译器在只是在.h文件中对class的声明,具体这个类里有什么信息,这里不需要知道,等实现的文件中真正要用到是,才会真正查看B类中的信息
3、@class的优点
使用@class由于只需要知道被引用的类的名称就可以了,而再实现类由于要用到被引用类中的实体变量和方法,所有在.m文件中需要使用#import来包含被引用的头文件
如果有上百个头文件都#import了同一个文件,或者这些文件一次被#import,那么一旦最开始的头文件稍有改动,后面引用到这个文件的所有类都需要重新编译一遍,这样的效率也是可想而知的,而相对来讲,使用@class方式就不会出现这种问题了。因此,使用@class可以大大提高文件编译的效率。
举例
//.h文件
#import
@class Book;
@interface Student
@property (retain) Book *book;
@end
#import "Student.h"
#import "Book.h"
//当调用Book类中的方法时就需要调用Book类
@implementation Student
@synthesize book = _book;
- (void)dealloc
{
[_book release];
[super dealloc];
}
@end
@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];
} // } 结束代表销毁释放池
2、使用注意
1)在ARC下,不能使用[[NSAutoreleasePool alloc] init],而应当使用@autoreleasepool
2)不要把大量循环操作放到同一个NSAutoreleasePool之间,这样会造成内存峰值的上升
3)尽量避免对大内存使用该方法,对于这种延迟释放机制,还是尽量少用
4)sdk中一般利用静态方法创建并返回的对象都是已经autorelease的,不需要再进行release操作
@autorelease的使用示例
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;
}
@autorelease的应用
/*
1.系统自带的方法里面没有包含alloc、new、copy,说明返回的对象都是autorelease的
2.开发中经常会提供一些类方法,快速创建一个已经autorelease过的对象
1> 创建对象时不要直接用类名,一般用self
+ (id)person
{
return [[[self alloc] init] autorelease];
}
*/
int main()
{
@autoreleasepool {
Person *p = [Person personWithAge:100];
GoodPerson *p2 = [GoodPerson personWithAge:10];
p2.money = 100;
}
return 0;
}
1、介绍
1)ARC,就是由编译器代码中自动加入了retain/release。要注意的是,ARC并不是GC,它只是一种代码静态分析工具
从iOS 5/Mac OS X 10.7开始导入,利用Xcode4.2可以使用该机制
2)优点:
1>不需要担心烦人的内存管理和内存泄露
2>代码的总量变少了
3>代码效率高,由于使用编译器管理引用计数,减少了低效代码的可能性
3)缺点:
1>要记住新的ARC规则、关键字、特性
2>使用一些旧代码、第三方代码的时候比较麻烦,可能要修改编译开关,XCode4.2中默认ARC是YES的状态
4)总结:系统引入一套自动管理内存的机制,回收并销毁对象
2、基本原理
1)规则
ARC 的规则非常简单:只要还有一个强指针变量指向对象,对象就会保持在内存中
2)强指针和弱指针
1>默认所有实例变量和局部变量都是Strong指针
2>弱指针指向的对象被回收后,弱指针会自动变为nil指针,不会引发野指针错误
3、使用注意
1)不能调用release、retain、autorelease、retainCount
2)可以重写dealloc,但是不能调用[super dealloc]
3)@property : 想长期拥有某个对象,应该用strong,其他对象用weak
4)其他基本数据类型依然用assign
5)两端互相引用时,一端用strong、一端用weak
4、ARC特点
1)不允许调用release、retain、retainCount
2)允许重写dealloc,但是不允许调用[super dealloc]
3)@property的参数
5)指针分2种:
1>强指针:默认情况下,所有的指针都是强指针 __strong
2> 弱指针:__weak
示例:效果很明显,怎么写都是对的!再也不用为内存而烦恼了!
//main.m文件
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;
}
// 微博内容、微博配图、发送时间、微博发送人、转发的微博、被评论数、被转发数
@interface Status : NSObject
@property (nonatomic, strong) NSString *text;
//retain改为strong
@property (nonatomic, strong) NSString *icon;
//默认使用atomic多线程,但是ios开发使用nonatomic即可
// 从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