分类: iOS平台
2015-03-24 18:17:21
1.内存管理
对基本数据类型无效
任何继承了NSObject的对象
2.每个对象内部都保存有整数,这个整数称之为引用计数器
当一个对象的引用计数器值为0的话,它将被销毁,占用的内存被系统回收,
OC会自动向对象发送dealloc消息,一定不要直接调用dealloc方法。
一般会重写dealloc方法,在里面释放相关资源。
3.当使用 alloc new copy 创建一个对象时,对象的引用计数器为1,该对象会一直存在内存中,除非用户关闭应用。
4.给对象发消息,就是调用对象方法
给对象发送retain消息,引用计数器+1
给对象发送release消息,引用计数器-1
5.给对象发送retainCount可以获得当前对象的引用计数器值
6.内存管理法则
谁创建,谁释放
谁retain 谁release
在哪个方法里创建,就在哪个方法里释放
7.内存管理的一个小例子
// Student.m
#import "Student.h"
@implementation Student
@synthesize age = _age;
-(void)dealloc{
NSLog(@"%@销毁了",self);
[super dealloc];//一定要调用super dealloc,最好放到最后面
}
@end
// main.m
#import
#import "Student.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Student *stu = [[Student alloc] init];
Student *stu1 = [[[Student alloc] init] autorelease];//在适当的时候,自动进行内存释放
NSLog(@"size--%zd",[stu retainCount]);
[stu retain];
NSLog(@"size--%zd",[stu retainCount]);
[stu release];
NSLog(@"size--%zd",[stu retainCount]);
[stu release];
//[stu release];//会导致野指针错误,内存已经被释放,指针还去访问他。
}
return 0;
}
8.注释
#pragma mark -生命周期方法 //- 代表给方法分组
#pragma mark 构造方法
9.对象之间的内存管理
// main.m
#import
#import "Student.h"
#import "Book.h"
void test(Student *stu){
Book *bo = [[Book alloc] initWithBook:9.9];
stu.book = bo;
[bo release];
}
void test1(Student *stu){
[stu readBook];//会引起野指针
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
Student *stu = [[Student alloc] initWithAge:39];
//Book *bo = [[Book alloc] initWithBook:3.2];
test(stu);
test1(stu);
[stu release];
//[bo release];
}
return 0;
}
// Student.m
#import "Student.h"
@implementation Student
//@synthesize age = _age;
-(void)dealloc{
NSLog(@"age--%d--销毁了",_age);
[super dealloc];
}
-(id)initWithAge:(int)age{
if((self = [super init]) != nil){
_age = age;
}
return self;
}
-(void)readBook{
NSLog(@"读的书是:%f",_book.price);
}
@end
上述代码会引起野指针
10.谁想使用对象,谁就retain
针对上述代码的改进,看下下面的代码
// Student.m
#import "Student.h"
@implementation Student
//@synthesize age = _age;
-(void)dealloc{
NSLog(@"age--%d--销毁了",_age);
[_book dealloc];//释放student时候释放book
[super dealloc];
}
-(id)initWithAge:(int)age{
if((self = [super init]) != nil){
_age = age;
}
return self;
}
-(void)readBook{
NSLog(@"读的书是:%f",_book.price);
}
-(void)setBook:(Book *)book{
_book = [book retain];//使用了就retain
}
-(Book *)book{
return _book;
}
@end
11.//修改这个函数后,还是会出现内存泄露
void test(Student *stu){
Book *bo = [[Book alloc] initWithBook:9.9];
stu.book = bo;
[bo release];
Book *bo1 = [[Book alloc] initWithBook:9.9];
stu.book = bo1;
[bo1 release];
}
12.OC里面给一个空的对象发送消息是不会错的
//防止上述内存泄露,可以这样写
-(void)setBook:(Book *)book{
//先释放就的成员变量,虽然有可能是nil
[_book release];
_book = [book retain];
}
13.[_book release];
[_book release];//这样是野指针,是不可以的
[nil release];//这样不是野指针,属于空指针,是可以的。
14.以下代码也会引起错误
void test(Student *stu){
Book *bo = [[Book alloc] initWithBook:19.9];
stu.book = bo;
[bo release];
stu.book = bo;//这里会引起野指针,因为重复调用了set方法
Book *bo1 = [[Book alloc] initWithBook:9.9];
stu.book = bo1;
[bo1 release];
}
15.写成这样会避免上诉情况
-(void)setBook:(Book *)book{
if(book != _book){
//先释放就的成员变量
[_book release];
_book = [book retain];
}
}
16.EXC_BAD_ACCESS 野指针错误