`
cenphoenix
  • 浏览: 160564 次
  • 性别: Icon_minigender_1
  • 来自: 大连
社区版块
存档分类
最新评论

Objective-C 2.0之前需要了解的:关于Obj-C内存管理的规则

阅读更多

Objective-C 2.0增加了一些新的东西,包括属性和垃圾回收。那么,我们在学习Objective-C 2.0之前,最好应该先了解,从前是什么样的,为什么Objective-C 2.0要增加这些支持。

这一切都跟Cocoa内存的管理规则有关系,我们知道,Objective-C中所有变量都定义为指针。指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址,如果使用不当,就会出错或者造成内存的泄露。要了解这些,就需要看看其内存管理的规则到底是什么样的。

这篇文章也应该做为苹果开发工具中提供的性能调试工具Instruments使用前必读知识进行阅读。Cocoa China将在稍后提供Instruments工具的使用方法,以及Objective-C 2.0的详细介绍。

要知道,如果你使用Objective-C 2.0,那么本文描述的大部分工作你都不需要自己去处理了。但是这并不意味着你可以不了解它,相反,只有你对内存管理规则更加了解,你才能更好地使用Objective-C 2.0带来的便利。

 

本文原文作者是Mmalcolm Crawford,原文地址  这篇文章翻译起来比较晦涩,希望您能看得懂。

 

当Cocoa新手在进行内存管理时,他们看上去总是把事情变得更为复杂。遵循几个简单的规则就可以把生活变得更简单。而不遵循这些规则,他们几乎一定会造成诸如内存泄露或者将消息发送给释放掉的对象而出现的的运行错误。

 

Cocoa不使用垃圾回收(当然,Objective-C 2.0之后开始就使用了),你必须通过计算reference的数量进行自己的内存管理,使用-retain ,  -release-autorelease

 

方法描述

-retain

将一个对象的reference数量增加1。

-release

将一个对象的reference数量减少1。

-autorelease

在未来某些时候将reference数量减少1.

-alloc

为一个对象分配内存,并设置保留值数量(retain count)为1。

-copy

复制一个对象,并将其做为返回值。同时设置保留值数量(retain count)为1。

保留值数量规则

1 在一定的代码段中,使用-copy-alloc-retain 的次数应该和-release-autorelease 保持一致。

2 使用便利构造方法创建的对象(比如NSStringstringWithString )可以被认为会被自动释放。(autoreleased)

3 在使用你自己的参数实例时,需要实现-dealloc 方法来释放。

例子

-alloc   /  -release

 

 

- (void )printHello 

{

NSString   *string;

string = [[ NSString  alloc]  initWithString: @"Hello" ];

NSLog (string);

//  我们用   alloc  创建了 NSString,那么需要释放它

[string  release ];

}

 

便利构造方法

 

 

- (void )printHello 

{

NSString   *string;

string = [ NSString  stringWithFormat: @"Hello" ];

NSLog (string);

//  我们用便利构造方法创建的 NSString

// 我们可以认为它会被自动释放

}

 

永远使用存取方法

虽然有时候你可能会认为这很麻烦,但是如果你始终使用了存取方法,造成内存管理问题的麻烦将会降低很多。

如果你在代码实例的参数中频繁使用-retain-release ,几乎可以肯定你做了错误的事情。

例子

假设我们希望设置一个Counter对象的数量值。

 

@interface   Counter : NSObject

{

NSNumber   *count;

}

 

为了获取和设置count值,我们定义两个存取方法:

 

- (NSNumber   *)count 

{

return   count;

//  无需 retain或者 release

//  仅仅传递数值

}

 

 

- (void )setCount:(NSNumber   *)newCount 

{

// newCount值会被自动释放,那么我们希望保留这个 newCount

//  所以需要在这里 retain

[newCount  retain ];

//  由于我们在这个方法中仅仅改变了计算数量的对象,我们可以在这里先释放它。因为[nil release]objective-c 中也是允许的,所以即使count 值没有被指定,也可以这样调用。

// 我们必须在[newCount retain] 之后再释放count ,因为有可能这两个对象的指针是同一个。我们不希望不小心释放它。

[count  release ];

//  重新指定

count = newCount;

}

 

命名约定

注意存取方法的命名约定遵循一个模式:  -参数名    -set参数名

遵循这一约定,会使你的代码可读性更强,而且,更重要地是你可以在后面使用key-value编码。(参阅NSKeyValueCoding协议)。

由于我们有一个对象实例参数,我们必须实现一个释放方法:

 

- (void )dealloc 

{

[ self  setCount: nil];

[ super  dealloc];

}

 

假设我们希望实现一个方法重置计数器,我们会有很多选择。在最开始,我们使用了一个 便利构造方法,所以我们假设新的数值是自动释放的。我们不需要发送任何retain 或者release 消息。

 

- (void )reset 

{

NSNumber  *zero = [ NSNumber  numberWithInt: 0 ];

[ self  setCount:zero];

}

 

然而,如果我们使用-alloc 方法建立的NSNumber 实例,那我们必须同时使用一个-release

 

 

- (void )reset 

{

NSNumber  *zero = [[ NSNumber  alloc]  initWithInt: 0 ];

[ self  setCount:zero];

[zero  release ];

}

常见错误

在简单的情况下,以下代码几乎一定可以正常运行,但是由于可能没有使用存取方法,下面的代码在某些情况下几乎一定会出问题。

 

错误-没有使用存取方法

 

- (void )reset 

{

NSNumber  *zero = [[ NSNumber  alloc]  initWithInt: 0 ];

[count  release ]

count = zero;

}

 

错误-实例泄露

 

 

- (void )reset 

{

NSNumber  *zero = [[ NSNumber  alloc]  initWithInt: 0 ];

[ self  setCount:zero];

}

 

新建的NSNumber 数值数量是1(通过alloc ),而我们在这个方法里没有发出-release 消息。那么这个NSNumber 就永远不会被释放了,这样就会造成内存泄露。

错误-对已经释放的实例发送-release 消息

 

 

- (void )reset 

{

NSNumber  *zero = [ NSNumber  numberWithInt: 0 ];

[ self  setCount:zero];

[zero  release ];

}

 

你随后在存取count的时候在这里就会出错。这个简便构造方法会返回一个自动释放的对象,你无需发送其他释放消息。

这样写代码意味着,由于对象已经被自动释放,那么当你释放时,retain count将被减至0,对象已经不存在了。当你下次希望获取count值时,你的消息会发到一个不存在的对象(通常这样你会得到一个SIGBUS 10的错误提示)。

经常造成混淆的情况

数组和其他集合类

当对象被加入到数组、字典或者集合中,集合类会将其保留。当集合被释放的同时,对象也会收到一个释放消息。如果你希望写一个建立数字数组的例子,你可能会这么写:

 

NSMutableArray *array;

int   i;

// …

for   (i =  0 ; i <  10 ; i++) 

{

NSNumber  *n = [ NSNumber  numberWithInt: i];

[array  addObject : n];

}

 

在这个例子里,你无需保留新建的数值,因为数组会帮你保留。

 

NSMutableArray *array;

int   i;

// …

for   (i =  0 ; i <  10 ; i++) 

{

NSNumber  *n = [[ NSNumber  alloc]  initWithInt: i];

[array  addObject : n];

[n  release];

}



本例中,在for 循环里你需要给n发送一个-release 消息,因为你需要始终在-alloc 之后将n的数量保持为1。这么做的原因是当其通过-addObject: 方法被添加至数组中时,数组已经将其保存起来。即使你释放了n,但是这个数字由于已经保存在数组里,所以不会被释放。

为了了解这些,假设你自己就是编写数组类的人。你不希望接收的对象未经你同意就消失,所以你会在对象传递进来时,对其发送一个-retain 消息。如果他们被删除,你同时也要对应地发送一个-release 消息。在你自己-dealloc 时,你也要给你收到的所有对象发送一个-release

from:Cocoa China

 

---------

 

什么是assign,copy,retain之间的区别?

  • assign: 简单赋值,不更改索引计数(Reference Counting)。
  • copy: 建立一个索引计数为1的对象,然后释放旧对象
  • retain:释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为

 

retain的实际语法为:

- (void)setName:(NSString *)newName {
    if (name != newName) {
       [name release];
       name = [newName retain];
       // name’s retain count has been bumped up by 1
    }
}
 ?如果你不懂怎么使用他们,那么就这样 ->

  • 使用assign: 对基础数据类型 (NSInteger,CGFloat)和C数据类型(int, float, double, char, 等等)
  • 使用copy: 对NSString
  • 使用retain: 对其他NSObject和其子类

分享到:
评论

相关推荐

    Objective-C+2.0之前需要了解的:关于Obj-C内存管理的规则

    Objective-C 是苹果开发环境下的主要编程语言,尤其在Objective-C 2.0之前的版本,内存管理是开发者必须亲力亲为的重要任务。...因此,熟悉这些基本的内存管理规则对于任何Objective-C开发者来说都是非常重要的。

    Effective Objective-C 2.0&Obj;-C高级编程

    "Effective Objective-C 2.0&Obj-C高级编程"这个压缩包文件包含了关于这个语言的深入学习资料,旨在帮助开发者提升他们的编程技能和理解。下面我们将详细探讨其中涉及的一些关键知识点。 1. **内存管理**: - ...

    The Objective-C 2.0 Programming Language

    ### 关于Objective-C 2.0编程语言的关键知识点 #### 一、Objective-C 2.0简介 Objective-C 2.0是一种通用的面向对象的编程语言,它是在早期版本的基础上进行了一系列重大改进的结果。Objective-C 2.0是苹果公司...

    Programming in Objective-C 2.0 2.pdf

    此外,Objective-C 2.0还增强了与C语言的互操作性,使得开发者可以在Objective-C代码中无缝地使用C代码,从而利用C语言的高效性和灵活性。 ### 面向对象编程 Objective-C是基于Smalltalk和C语言的一种面向对象编程...

    obj-c2.0大全

    - **内存管理**:Obj-C提供了一套内存管理规则,包括`alloc`, `new`, `copy`, `autorelease`, `release`等方法。 - **自动引用计数(Automatic Reference Counting, ARC)**:Obj-C2.0中引入的重要特性之一,可以自动...

    多态在Objective-C中的魔法:深入探索面向对象编程的高级特性

    5. **内存管理**:Objective-C最初使用引用计数进行内存管理,但随着ARC(自动引用计数)的引入,开发者可以更容易地管理内存。 6. **框架丰富**:Objective-C拥有大量的框架,这些框架为开发者提供了丰富的功能,...

    Objective-C 运行时魔法:动态方法解析与消息机制深度探秘

    Objective-C(通常缩写为Obj-C或简称OC)是一种面向...5. **类别(Categories)**:Objective-C允许向现有的类添加新的方法,而不需要修改类的源代码。 6. **协议(Protocols)**:Objective-C使用协议定义对象之间

    From C++ to Objective-C.pdf

    - **ARC(Automatic Reference Counting)**: ARC是一种自动引用计数技术,自iOS 5和OS X Lion以来成为标准,它取代了传统的手动内存管理机制(MRR),进一步简化了Objective-C的内存管理。 #### 4. Cocoa与Objective-C...

    掌握撤销的艺术:深入探索Objective-C中的NSUndoManager

    Objective-C(通常缩写为Obj-C或OC)是一种通用的面向对象编程语言,它将Smalltalk风格的消息传递机制添加到了C语言中。Objective-C是由Brad Cox和Tom Love在1980年代初期开发出来的,最初是作为C语言的一个扩展。它...

    探索Objective-C中的Block:强大灵活的代码块

    Objective-C(通常缩写为Obj-C或OC)是一种通用的编程语言,它主要被用于苹果公司的操作系统,如macOS和iOS,以及它们的应用开发框架,如Cocoa和Cocoa Touch。Objective-C是C语言的一个超集,这意味着它包含了C语言...

    From C++ to Objective-C

    - **Objective-C与Cocoa的关系**:Objective-C是Cocoa和Cocoa Touch框架的核心编程语言,它提供了一种结构化的方式来组织和管理代码,使得开发者能够高效地创建复杂的应用程序。 ##### 1.2 Objective-C的历史 ...

    objective-c内存管理

    Objective-C的内存管理机制与.NET和Java等语言中常见的自动垃圾回收机制不同,它更接近于C语言的手动管理方式,但在此基础上加入了一些自动化手段,使得开发人员能够在一定程度上简化内存管理的工作。 ##### 1. ...

    Object-C语言教程&案例&相关项目资源

    - **起源**:Objective-C最早是由Brad Cox和Tom Love在1980年代初设计的,旨在结合C语言的强大功能和Smalltalk面向对象的优势。 - **特性**: - 支持面向对象编程概念,如类、对象、继承、封装和多态。 - 保留了...

    Learn Objective-C on the Mac eBook.pdf (incl. examples) 包含全代码

    此外,本书还将涵盖内存管理,Objective-C使用引用计数来管理内存,你需要理解“retain”、“release”和“autorelease”等概念,以及后来引入的ARC(Automatic Reference Counting)自动引用计数,它极大地简化了...

    Objective -C 基础教程 的代码

    Objective-C 是基于C语言的,它添加了消息传递机制、类和协议等面向对象的特性。消息传递是Objective-C中的核心概念,通过`[receiver message]`的形式进行调用。类定义了对象的结构和行为,而协议则允许实现接口...

Global site tag (gtag.js) - Google Analytics