位置:首页 > > Objective-C 内存管理

Objective-C 内存管理

内存管理是任何编程语言中最重要的过程之一。它是一个过程,通过该对象的内存时,需要时分配,当不再需要时释放。

管理对象的内存性能是一个问题,如果一个应用程序没有免费的不需要的对象,其内存占用量的增长和性能将受到影响。

Objective-C的内存管理技术大致可分为两类。

  • “手动保留释放”或MRR

  • “自动引用计数”或ARC

“手动保留释放”或MRR

在 MRR中,我们明确地管理内存,在我们自己的跟踪对象。这是使用一种模式,被称为引用计数,基础类NSObject 提供配合运行环境。

MRR 和 ARC 之间的唯一区别是,保留和释放处理前手动而随后自动处理。

下图表示如何在Objective-C 内存管理工作的一个例子。

Objective-C Memory management

在上图中所示的A类对象的存储生命周期。正如可以看到,如下图所示的对象保留计数,当保留计数的对象变为0的,对象是完全释放,其它对象使用的内存被释放。

A类对象第一次被创建,使用分配/ NSObject的init方法。现在,保留计数变为1。

现在,B类保留A类的对象和保留计数类A的对象变成2。

然后,C类对象的一个副本。现在,它被创建为A类的实例变量的值相同的另一个实例。在这里,保留计数为1,而不是原来的对象的保留计数。这在图中由虚线表示。

复制的对象将释放C类使用释放方法,并保留计数变为0,因此对象被销毁。

在初始A类对象的情况下,保留计数为2,它有两次被释放,以便将其销毁。这是通过类A和B类保留计数递减为1和0,分别使用 release 语句。最后,对象将被破坏。

MRR基本规则

  • 我们拥有我们所创建的任何对象:我们创建了一个对象,使用方法的名字以 "alloc", "new", "copy" 或 "mutableCopy"开始

  • 我们可以把一个对象使用保留所有权:接收到的对象通常是保证在收到它的方法仍然有效,并且该方法也可以安全地返回其调用对象。我们使用保留在两种情况下:

    • 在执行存取方法或者一个init方法,采取所有权,我们要存储一个对象的属性值。

    • 为了防止一个对象被无效的一些其他的操作的一个副作用。

  • 当我们不再需要它,我们必须放弃所有权的对象,我们自己:我们放弃对象的所有权,通过发送一个释放消息或一个自动释放的消息。在可可术语,放弃一个对象的所有权,因此通常被称为“释放”一个对象。

  • 不能放弃拥有一个对象(不属于自己):这只是推论明确说明以前的策略规则。

#import <Foundation/Foundation.h>

@interface SampleClass:NSObject
- (void)sampleMethod;
@end

@implementation SampleClass

- (void)sampleMethod
{
   NSLog(@"Hello, World! 
");
}

- (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中我们需要不加释放和保留的方法,因为这将得到编译器的处理。事实上,底层的 Objective-C 程序仍然是一样的。它使用的保留和释放内部的操作使它更容易为开发人员代码不担心这些操作的情况下,这将减少代码编写量和内存泄漏的可能性。

还有另一个称为垃圾收集的原则,这是用来在Mac OS-X以及MRR,但其在OS-XMountain Lion 中弃用以来,它已经不随着MRR讨论。此外,iOS 的对象从未有过的垃圾收集特点。较ARC,在OS-X是没有用垃圾收集。

下面是一个简单的ARC例子

#import <Foundation/Foundation.h>

@interface SampleClass:NSObject
- (void)sampleMethod;
@end

@implementation SampleClass

- (void)sampleMethod
{
   NSLog(@"Hello, World! ");
}

- (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