内存管理
- dealloc
当对象的引用计数变为 0 时,系统会给该对象发送 dealloc 消息释放内存。
MRC
// Teacher.h
#import <Foundation/Foundation.h>
@interface Teacher : NSObject
@property (nonatomic , copy) NSString *name;
@end
// Teacher.m
#import "Teacher.h"
@implementation Teacher
- (void) dealloc {
NSLog(@"Teacher dealloc called");
[super dealloc];
}
@end
// Student.h
#import <Foundation/Foundation.h>
#import "Teacher.h"
@interface Student : NSObject
@property (nonatomic , retain) Teacher *teacher;
@end
// Student.m
#import "Student.h"
@implementation Student
- (void) dealloc {
NSLog(@"Student dealloc called");
[self.teacher release]; // teacher count == 0 | teacher dealloc
[super dealloc];
}
// 调用
Teacher *teacher = [[Teacher alloc]init]; // teacher count == 1
teacher.name = @"MissLiu";
Student *student = [[Student alloc]init]; // student count == 1
student.teacher = teacher; // teacher count == 2
[teacher release]; // teacher count == 1
[student retain]; // student count == 2
[student release]; // student count == 1
[student release]; // student dealloc
@end
// 打印
2017-03-31 14:10:14.069 MRC[30203:6093362] Student dealloc called
2017-03-31 14:10:14.070 MRC[30203:6093362] Teacher dealloc called
小结:
- dealloc 实际释放的是堆内存(系统无法自动回收)
- 对使用了 retain、copy、mutableCopy、alloc 或者 new 方法的任何对象,以及具有 retain 和 copy 特性的属性进行释放,需要覆盖 dealloc 方法,使得在对象被释放的时候能够释放这些实例变量。
ARC
- (void) dealloc {
NSLog(@"dealloc called"); // 监听对象是否释放
}
autorelease
- 将对象放入
自动释放池栈栈顶的自动释放池中。 - 自动释放池销毁或者调用 drain 消息时 对象会调用 release 消息
自动释放池
// 正确的三种写法
// 使用 @autoreleasepool 创建一个自动释放池放于栈顶
@autoreleasepool {
Student *s1 = [Student new];
[s1 retain];
[s1 release]; // count == 1
[s1 autorelease]; // 将 s1 放入栈顶的自动释放池,当自动释放池销毁或者调用 drain 消息时 s1 会调用 release 消息
s1.name = @"iMock"; // 此时 s1 指针指向的堆内存还没有释放。
}
// 自动释放池销毁,池中的每个对象都会收到 release 消息。此时 s1 指针指向的堆内存释放
// 等效于第一种写法
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
Student *s2 = [Student new];
[s2 retain];
[s2 release];
[s2 autorelease];
s2.name = @"iMock";
[pool release];
// 不创建新的自动释放池,将 s3 放入当前栈顶的自动释放池
Student *s3 = [Student new];
[s3 retain];
[s3 release];
[s3 autorelease];
s3.name = @"iMock";
小结:
- 推迟调用 release 的时间。
- 自动释放池中存放的都是对象的引用。
- 由一个自动释放池栈维护。
- 自动释放池对象调用 drain 消息,会给池中的每个对象发一次 release 消息。
- 自动释放池对象调用 release 消息,会给池中的每个对象发一次 release 消息,同时会销毁自己。

浙公网安备 33010602011771号