“手动保留释放”(MRR)
在MRR中,我们通过自己跟踪对象来显式管理内存。这是使用Foundation类NSObject与运行时环境一起提供的称为引用计数的模型来实现的。MRR和ARC之间的唯一区别是,保留和释放是由我们在前者中手动处理的,而由我们在后者中自动处理。下图代表了Objective-C中内存管理的工作方式示例。
上图显示了A类对象的内存生命周期。如您所见,保留计数显示在对象的下方,当对象的保留计数变为0时,该对象被完全释放,其内存被释放以供其他对象使用。类首先使用NSObject中可用的alloc/init方法创建对象。现在,保留计数变为1。现在,类B保留了类A的对象,并且类A的对象的保留计数变为2。然后,类C复制该对象。现在,它被创建为类A的另一个实例,并且实例变量的值相同。此处,保留计数为1,而不是原始对象的保留计数。这由图中的虚线表示。类C使用释放方法释放了复制的对象,并且保留计数变为0,因此该对象被破坏。对于初始的A类对象,保留计数为2,必须将其释放两次才能销毁。这是通过Class A和Class B的release语句将保留计数分别递减为1和0来完成的。最后,对象被销毁。
MRR基本规则
- 我们拥有我们创建的任何对象:我们使用名称以“ alloc”,“ new”,“copy”或“ mutableCopy”开头的方法创建对象
- 我们可以使用keep来获得对象的所有权:通常可以保证接收到的对象在接收该对象的方法中保持有效,并且该方法还可以安全地将该对象返回给其调用者。我们在两种情况下使用保留-
- 在访问器方法或init方法的实现中,要获取我们要存储为属性值的对象的所有权。
- 防止由于其他操作的副作用而使对象无效。
- 当我们不再需要它时,我们必须放弃对自己拥有的对象的所有权:我们通过发送释放消息或自动释放消息来放弃对对象的所有权。因此,在可可术语中,放弃对象的所有权通常称为“释放”对象。
- 您不得放弃不拥有的对象的所有权:这只是先前明确规定的先前策略规则的必然结果。
#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() {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
/* 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;
[pool drain];
return 0;
}
现在,当我们编译并运行程序时,我们将得到以下结果。
2020-08-25 10:30:53.238 helloWorld[13092:2856] Hello, World!
2020-08-25 10:30:53.244 helloWorld[13092:2856] Retain Count after initial allocation: 1
2020-08-25 10:30:53.244 helloWorld[13092:2856] Retain Count after retain: 2
2020-08-25 10:30:53.244 helloWorld[13092:2856] Retain Count after release: 1
2020-08-25 10:30:53.244 helloWorld[13092:2856] Object deallocated
2020-08-25 10:30:53.244 helloWorld[13092:2856] SampleClass dealloc will be called before this