iOS 应用程序中会出现crash ,90%以上原因是内存问题。
了解内存问题并掌握内存管理的机制,就能减少出错几率,提高程序性能,大大减少调试时间。
常见内存问题:内存溢出,野指针异常。
首先,我们建立1个类:
import <Foundation/Foundation.h>
@interface Person : NSObject <NSCopying>
{
NSString *_name;
}
/// 初始化方法
- (id)initWithName:(NSString *)name;
/// 便利构造器
+ (id)personWithName:(NSString *)name;
实现部分:
#import "Person.h"
- (id)initWithName: (NSString *)name
{
self = [super init];
if (self) {
_name = name;
}
return self;
}
/// 便利构造器
+ (id)personWithName:(NSString *)name
{
Person *p = [[[Person alloc] initWithName:name] autorelease]; //自动释放
return p;
}
/// 实现协议copy的方法
- (id)copyWithZone:(NSZone *)zone
{
Person *p = [[Person allocWithZone:zone]
initWithName:[NSString stringWithFormat:@"%@的克隆人", _name]];
return p;
}
/// 重写父类的dealloc方法
- (void)dealloc //验证对象引用计数是否为0;
{
NSLog(@"%@%@对象被销毁了", self, _name);
//对成员变量释放
// [_name release];
// _name = nil;
[super dealloc];
}
@end
main.m
Person *jingGeGe = [[Person alloc] initWithName:@"靖哥哥"];//1 //开辟内存空间,引用计数由0变1;
NSLog(@"%p", &jingGeGe); //栈的地址
NSLog(@"jingGeGe: %p", jingGeGe); //堆的地址
NSLog(@"%ld", [jingGeGe retainCount]); //引用计数变为1;
Person *dongJing = [jingGeGe retain];//2 //主张对象持有权,引用计数累加1;
NSLog(@"%ld", [dongJing retainCount]); //引用计数变为2;
NSLog(@"dongJing: %p", dongJing);
[dongJing release]; //释放对象,不再持有,引用计数未来减一
NSLog(@"%ld", [jingGeGe retainCount]); //引用计数变为1;
NSLog(@"%ld", [dongJing retainCount]); //不是内存被回收,还可以用
dongJing = nil; //对象为空
[dongJing release]; //[nil release] 向一个空对象发送任何消息,不会产生任何效果,不会报错,不会crash
NSLog(@"%ld", [dongJing retainCount]); //对象赋予nil 时,计数输出为0;
[jingGeGe release]; //引用计数变为0;全部被回收
NSLog(@"%ld", [jingGeGe retainCount]); //输出计数还是1!
// [jingGeGe release]; //野指针,crash
/*
野指针异常主要成因:
一、指针变量没有被初始化
二、对象的内存空间已经被回收,仍然使用指针操作这块内存
// (自动释放)autorelease的好处与习惯用法
Person *laoWang = [[Person alloc] initWithName:@"隔壁老王"]; //1
// [laoWang retain]; //2,引用计数加1,变为2. 不写就会被销毁!写了还剩1.
[laoWang autorelease];
NSLog(@"%ld", [laoWang retainCount]); //2
OC采用引用计数(retain count)记录某块内存持有者的个数。当对象的内存多了一个持有者,引用计数器就递增,少了一个所有者,引用计数就递减。当引用计数到零时,该对象就将释放占有的资源。
+ alloc //开辟内存空间,引用计数由0变1;
- retain //主张对象持有权,引用计数累加1;
- release //释放对象,不再持有,引用计数减1;
- autorelease // 自动释放对象,引用计数未来减1;
- copy // 拷贝创建一个对象,原有对象引用计数不变。
内存管理原则:
• You own any object you create by allocating memory for it or copying it.Related methods: alloc, allocWithZone:, copy, copyWithZone:, mutableCopy, mutableCopyWithZone:
• If you are not the creator of an object, but want to ensure it stays in memory for you to use, you can express an ownership interest in it. Related method: retain
• If you own an object, either by creating it or expressing an ownership interest, you are responsible for releasing it when you no longer need it.Related methods: release, autorelease
• Conversely, if you are not the creator of an object and have not expressed an ownership interest, you must not release it.