减少内存碎片
- 对象池(Object Pooling):
- 原理:预先创建一组对象并放入对象池中,当需要新对象时,从对象池中获取,使用完毕后再放回对象池,而不是频繁地创建和销毁。在Objective - C中,可以使用
NSMutableArray
或NSCache
来实现简单的对象池。例如,对于频繁使用的视图对象(如UITableViewCell
),iOS的UITableView
就使用了类似对象池的机制(dequeueReusableCellWithIdentifier:
方法)。
- 内存布局优势:减少了频繁内存分配和释放导致的内存碎片化。因为对象的创建和销毁集中在初始化和清理阶段,而不是在程序运行期间随意地进行,使得内存使用更加紧凑。
- 内存对齐优化:
- 原理:Objective - C对象的内存布局遵循一定的对齐规则。了解对象的成员变量类型和大小,合理安排成员变量顺序,使对象整体占用的内存空间最小化且满足对齐要求。例如,
NSObject
本身占用8字节(64位系统),如果一个自定义类继承自NSObject
且包含一个int
(4字节,64位系统)和一个double
(8字节)成员变量,按照double
在前int
在后的顺序定义成员变量,对象整体只需要16字节(满足8字节对齐);若顺序相反,则需要24字节(先按4字节对齐int
,再按8字节对齐double
,最后整体按8字节对齐)。
- 内存布局优势:通过优化内存对齐,可以减少对象之间的空闲空间,提高内存利用率,进而减少内存碎片。
精准控制对象释放时机
- 自动释放池(Autorelease Pool):
- 原理:自动释放池是Objective - C内存管理中的一个重要机制。当一个对象发送
autorelease
消息时,它被添加到最近的自动释放池中。当自动释放池被销毁时,池中的所有对象都会收到release
消息。在一个具有大量对象创建和销毁的循环中,可以手动创建自动释放池块。例如:
@autoreleasepool {
for (int i = 0; i < 10000; i++) {
NSString *string = [[NSString alloc] initWithFormat:@"%d", i];
// 使用string
[string autorelease];
}
}
- 释放时机优势:通过这种方式,可以在循环执行过程中及时释放不再使用的对象,而不是等到当前作用域结束(如果没有手动创建自动释放池,对象会在最近的自动释放池销毁时才释放,可能会导致内存占用过高),从而减少内存峰值。
- 弱引用(Weak References):
- 原理:在ARC(自动引用计数)环境下,
__weak
修饰符用于创建弱引用。弱引用不会增加对象的引用计数,当对象的引用计数变为0并被销毁时,指向该对象的所有弱引用会自动被设置为nil
。例如,在视图控制器之间的父子关系中,父视图控制器持有子视图控制器的强引用,而子视图控制器中对父视图控制器的引用可以使用弱引用,以避免循环引用。
@interface ChildViewController : UIViewController
@property (nonatomic, weak) ParentViewController *parentVC;
@end
- 释放时机优势:通过使用弱引用,可以打破循环引用,确保对象在没有强引用指向它时能及时被释放,精准控制对象的生命周期。
- 运行时动态方法替换:
- 原理:利用Objective - C运行时的
class_replaceMethod
等函数,可以在运行时动态替换对象的方法。例如,可以在对象即将释放时,动态替换其dealloc
方法,添加一些额外的清理逻辑,或者记录对象释放的相关信息。
#import <objc/runtime.h>
void myDealloc(id self, SEL _cmd) {
// 自定义清理逻辑
NSLog(@"Object is being deallocated");
// 调用原始的dealloc方法
Method originalMethod = class_getInstanceMethod([self class], @selector(dealloc));
((void (*)(id, SEL))method_getImplementation(originalMethod))(self, _cmd);
}
void replaceDeallocMethod(Class class) {
class_replaceMethod(class, @selector(dealloc), (IMP)myDealloc, method_getTypeEncoding(class_getInstanceMethod(class, @selector(dealloc))));
}
- 释放时机优势:通过动态替换
dealloc
方法,可以更灵活地控制对象释放时的行为,确保在对象释放前完成所有必要的清理工作,避免潜在的内存泄漏或资源未释放问题。