OC对象的内存管理 MRC手动内存管理
- 在iOS中,使用引用计数来管理OC对象的内存,基本数据类型不需要内存管理。
- 一个新创建的OC对象引用计数默认是1,当引用计数减为0,OC对象就会销毁,释放其占用的内存空间
- 调用retain会让OC对象的引用计数+1,调用release会让OC对象的引用计数-1
- 内存管理的经验总结
-
xxx.retainCount //查看引用计数。
-
当调用alloc、new、copy、mutableCopy方法返回了一个对象,在不需要这个对象时,要调用release或者autorelease来释放它
-
想拥有某个对象,就让它的引用计数+1;不想再拥有某个对象,就让它的引用计数-1
-
- 实践
- 关闭自动引用计数管理
- 最基本的手动引用计数管理
- 由于无法确认在什么时候释放内存比较好使用 autorelease 会自动释放
void test()
{
// 内存泄漏:该释放的对象没有释放
// MJPerson *person1 = [[[MJPerson alloc] init] autorelease];
// MJPerson *person2 = [[[MJPerson alloc] init] autorelease];
}
- 类与类之间是互相关联的时候怎么使用
- 假设person中拥有dog成员属性的时候,这个dog要怎么管理内存呢
- 源码
- MJPerson.h
#import <Foundation/Foundation.h>
#import "MJDog.h"
@interface MJPerson : NSObject
{
MJDog *_dog;
int _age;
}
- (void)setAge:(int)age;
- (int)age;
- (void)setDog:(MJDog *)dog;
- (MJDog *)dog;
@end
- MJPerson.m
#import "MJPerson.h"
@implementation MJPerson
- (void)setAge:(int)age
{
_age = age;
}
- (int)age
{
return _age;
}
- (void)setDog:(MJDog *)dog
{
if (_dog != dog) {
[_dog release];
_dog = [dog retain];
}
}
- (MJDog *)dog
{
return _dog;
}
- (void)dealloc
{
// [_dog release];
// _dog = nil;
self.dog = nil; //调用了set方法释放了内存。
NSLog(@"%s", __func__);
// 父类的dealloc放到最后
[super dealloc];
}
@end
- MJDog.h
#import <Foundation/Foundation.h>
@interface MJDog : NSObject
- (void)run;
@end
- MJDog.m
#import "MJDog.h"
@implementation MJDog
- (void)run
{
NSLog(@"%s", __func__);
}
- (void)dealloc
{
[super dealloc];
NSLog(@"%s", __func__);
}
@end
- MJDog.h
#import <Foundation/Foundation.h>
@interface MJDog : NSObject
- (void)run;
@end
- MJDog.m
#import "MJDog.h"
@implementation MJDog
- (void)run
{
NSLog(@"%s", __func__);
}
- (void)dealloc
{
[super dealloc];
NSLog(@"%s", __func__);
}
@end
- 调用
void test2()
{
MJDog *dog = [[MJDog alloc] init]; // 1
MJPerson *person1 = [[MJPerson alloc] init];
[person1 setDog:dog]; // 2
MJPerson *person2 = [[MJPerson alloc] init];
[person2 setDog:dog]; // 3
[dog release]; // 2
[person1 release]; // 1
[[person2 dog] run];
[person2 release]; // 0
}
- 替换属性 旧的先释放,新的在+1.
- 分析
- 1.MJDog *dog = [[MJDog alloc] init]; // 1 dog类计数1
- 2.[person1 setDog:dog]; 调用 -> _dog = [dog retain]; //dog 计数+1 = 2
- 3.[person2 setDog:dog]; // 3
- 4.[dog release]; // 2 对应了第一条创建的指令 -1后=2
- 5.[person1 release]; // 1 [person2 release]; // 0 person类自己计数减一后调用自身的dealloc,将person中的拥有的成员变量的引用计数-1,所以dog分别减了2次最后dog类引用计数变成为0,释放了内存。
- 优化代码
- MJPerson.h
#import <Foundation/Foundation.h>
#import "MJDog.h"
@property (nonatomic, assign) int age; //assign 是直接赋值的意思。
@property (nonatomic, retain) MJDog *dog; //对象类型使用,对象被替换时,会自动判断后再赋值。释放旧的内存-1,对新的内存+1。注意点:delloc的时候要把成员变量设置为nil.
+ (instancetype)person;
@end
- MJPerson.m
#import "MJPerson.h"
@implementation MJPerson
+ (instancetype)person
{
return [[[self alloc] init] autorelease];
}
- (void)dealloc
{
self.dog = nil;
self.car = nil;
NSLog(@"%s", __func__);
[super dealloc];
}
@end