- Objective-C 基础
- Objective-C - 首页
- Objective-C - 概述
- Objective-C - 环境搭建
- Objective-C - 程序结构
- Objective-C - 基本语法
- Objective-C - 数据类型
- Objective-C - 变量
- Objective-C - 常量
- Objective-C - 运算符
- Objective-C - 循环
- Objective-C - 决策
- Objective-C - 函数
- Objective-C - 块
- Objective-C - 数字
- Objective-C - 数组
- Objective-C - 指针
- Objective-C - 字符串
- Objective-C - 结构体
- Objective-C - 预处理器
- Objective-C - Typedef
- Objective-C - 类型转换
- Objective-C - 日志处理
- Objective-C - 错误处理
- 命令行参数
- 高级 Objective-C
- Objective-C - 类与对象
- Objective-C - 继承
- Objective-C - 多态
- Objective-C - 数据封装
- Objective-C - 类别
- Objective-C - 模拟
- Objective-C - 扩展
- Objective-C - 协议
- Objective-C - 动态绑定
- Objective-C - 复合对象
- Obj-C - Foundation 框架
- Objective-C - 快速枚举
- Obj-C - 内存管理
- Objective-C 有用资源
- Objective-C - 快速指南
- Objective-C - 有用资源
- Objective-C - 讨论
Obj-C 内存管理
内存管理是任何编程语言中最重要的一项过程。它是分配对象内存(当需要时)并在不再需要时释放内存的过程。
管理对象内存是一个性能问题;如果应用程序不释放不需要的对象,则其内存占用量会增加,从而导致性能下降。
Objective-C 内存管理技术可以大致分为两种类型。
- “手动保留-释放”或 MRR
- “自动引用计数”或 ARC
“手动保留-释放”或 MRR
在 MRR 中,我们通过自己跟踪对象来显式管理内存。这是使用引用计数模型实现的,该模型由 Foundation 类 NSObject 与运行时环境一起提供。
MRR 和 ARC 之间的唯一区别在于,在 MRR 中,retain 和 release 由我们手动处理,而在 ARC 中,则由系统自动处理。
下图展示了 Objective-C 中内存管理的工作原理示例。
上图显示了类 A 对象的内存生命周期。如您所见,保留计数显示在对象下方,当对象的保留计数变为 0 时,该对象将被完全释放,并且其内存将被释放供其他对象使用。
类 A 对象首先使用 NSObject 中可用的 alloc/init 方法创建。现在,保留计数变为 1。
现在,类 B 保留类 A 的对象,类 A 对象的保留计数变为 2。
然后,类 C 创建对象的副本。现在,它被创建为类 A 的另一个实例,实例变量具有相同的值。在这里,保留计数为 1,而不是原始对象的保留计数。图中虚线表示这一点。
类 C 使用 release 方法释放复制的对象,保留计数变为 0,因此对象被销毁。
对于初始的类 A 对象,保留计数为 2,并且必须释放两次才能销毁它。这是通过类 A 和类 B 的 release 语句完成的,它们分别将保留计数递减到 1 和 0。最后,对象被销毁。
MRR 基本规则
我们拥有我们创建的任何对象:我们使用名称以“alloc”、“new”、“copy”或“mutableCopy”开头的方法创建对象
我们可以使用 retain 获取对象的所有权:接收到的对象通常保证在其接收到的方法内保持有效,并且该方法也可以安全地将对象返回给其调用者。我们在两种情况下使用 retain -
在访问器方法或 init 方法的实现中,获取我们想要存储为属性值的对象的所有权。
防止对象因其他操作的副作用而失效。
当我们不再需要它时,我们必须放弃我们拥有的对象的所有权:我们通过向对象发送 release 消息或 autorelease 消息来放弃对象的所有权。在 Cocoa 术语中,放弃对象的所有权因此通常称为“释放”对象。
您不得放弃您不拥有的对象的所有权:这只是先前策略规则的推论,已明确说明。
#import <Foundation/Foundation.h>
@interface SampleClass:NSObject
- (void)sampleMethod;
@end
@implementation SampleClass
- (void)sampleMethod {
NSLog(@"Hello, World! \n");
}
- (void)dealloc {
NSLog(@"Object deallocated");
[super dealloc];
}
@end
int main() {
/* my first program in Objective-C */
SampleClass *sampleClass = [[SampleClass alloc]init];
[sampleClass sampleMethod];
NSLog(@"Retain Count after initial allocation: %d",
[sampleClass retainCount]);
[sampleClass retain];
NSLog(@"Retain Count after retain: %d", [sampleClass retainCount]);
[sampleClass release];
NSLog(@"Retain Count after release: %d", [sampleClass retainCount]);
[sampleClass release];
NSLog(@"SampleClass dealloc will be called before this");
// Should set the object to nil
sampleClass = nil;
return 0;
}
当我们编译上述程序时,我们将获得以下输出。
2013-09-28 04:39:52.310 demo[8385] Hello, World! 2013-09-28 04:39:52.311 demo[8385] Retain Count after initial allocation: 1 2013-09-28 04:39:52.311 demo[8385] Retain Count after retain: 2 2013-09-28 04:39:52.311 demo[8385] Retain Count after release: 1 2013-09-28 04:39:52.311 demo[8385] Object deallocated 2013-09-28 04:39:52.311 demo[8385] SampleClass dealloc will be called before this
“自动引用计数”或 ARC
在自动引用计数或 ARC 中,系统使用与 MRR 相同的引用计数系统,但它在编译时为我们插入了适当的内存管理方法调用。强烈建议您在新的项目中使用 ARC。如果我们使用 ARC,通常不需要理解本文档中描述的底层实现,尽管在某些情况下它可能会有所帮助。有关 ARC 的更多信息,请参阅 迁移到 ARC 发行说明。
如上所述,在 ARC 中,我们不需要添加 release 和 retain 方法,因为编译器会处理这些方法。实际上,Objective-C 的底层过程仍然相同。它在内部使用 retain 和 release 操作,使开发人员更容易编写代码而无需担心这些操作,从而减少了编写的代码量和内存泄漏的可能性。
还有另一个称为垃圾回收的原理,它与 MRR 一起用于 Mac OS-X,但由于它在 OS-X Mountain Lion 中已被弃用,因此不再与 MRR 一起讨论。此外,iOS 对象从未有过垃圾回收功能。并且使用 ARC,OS-X 中也不再使用垃圾回收。
这是一个简单的 ARC 示例。请注意,这在在线编译器上不起作用,因为它不支持 ARC。
#import <Foundation/Foundation.h>
@interface SampleClass:NSObject
- (void)sampleMethod;
@end
@implementation SampleClass
- (void)sampleMethod {
NSLog(@"Hello, World! \n");
}
- (void)dealloc {
NSLog(@"Object deallocated");
}
@end
int main() {
/* my first program in Objective-C */
@autoreleasepool {
SampleClass *sampleClass = [[SampleClass alloc]init];
[sampleClass sampleMethod];
sampleClass = nil;
}
return 0;
}
当我们编译上述程序时,我们将获得以下输出。
2013-09-28 04:45:47.310 demo[8385] Hello, World! 2013-09-28 04:45:47.311 demo[8385] Object deallocated