`

[转]NSMutableArray中的自动释放对象让我郁闷了一整天

    博客分类:
  • ios
 
阅读更多

转自:http://w11h22j33.iteye.com/blog/1441738

 

在做一个TableView程序时,要在表格里显示一个文件夹内所有文件的清单,程序在一开始显示时正常,但是一滚动窗口时就崩溃,查找这个错误整整花了我一天的时间,原来出在NSMutableArray初始化时用的方法不正确,都是因为Objective-C的基础知识没学好。

在一个UITableViewController类中声明了一个NSMutableArray *localFiles这样一个数组,作为成员变量。

在viewDidLoad方法中读出应用程序Documents目录下的所有文件名放在这个数组中,初始化时用了这个方法:

localFiles = [NSMutableArray array];    //这是自动释放的对象

然后循环调用了addObject方法,其它就没有什么特殊的操作了,程序能够显示出一个文件列表,但向上或向下滚动一点点时,程序就崩溃,显示的错误信息也相当奇怪:

[__NSArrayI addObject:]: unrecognized selector sent to instance 0x4b1b8b0

我查啊查啊,每次出错的调用栈都显示在执行到cellForRowAtIndexPath这个方法时出错,跟踪到localFiles这个变量时,在调试器上显示out of scope,这个localFiles指针里的内容不知道跑到哪里去了。

从google上查了许多资料,在这个网站的留言中查到下面一段话,顿时茅塞顿开:

It doesn't really matter. [NSMutableArray array] is a nice shortcut, but you have to remember to retain it, so the question really is a matter of [[NSMutableArray array] retain] versus [[NSMutableArray alloc] init]. I usually use the former. The real convenience comes in when you need to statically fill the array; you can do it all in one message. [[NSMutableArray arrayWithObjects:...] retain] is faster than [[NSMutableArray alloc] init] followed by numerous [NSMutableArray addObject:(id)] calls.

原来在调用array方法后得retain!或者改用[[NSMutableArray alloc] init]方法组合,试了2种修改办法果然都好用,程序再也不崩溃了。就这么几个字,害了我几乎一整天。

localFiles = [[NSMutableArray array] retain];

这一天里恶补了一些Objective-C中的内存管理知识,虽然走了一些弯路,但对AutoRelease这个术语算是有了一些认识了。

 

后来仔细看了《Objective C教程》的第9章“内存管理”,原来第9.3节“Cocoa内存管理规则”(第138页)里作者早就强调三条规则:

(1)当你使用new、alloc或copy方法创建一个对象时,该对象的引用计数器值为1。当不再使用该对象时,你要负责向该对象发送一条release或autorelease消息。这样,该对象将在其使用寿命结束时被销毁。

(2)当你通过任何其它方法获得一个对象时,则假设该对象的引用计数器值为1,而且已经被设置为自动释放,你不需要执行任何操作来确保该对象被清理。如果你打算在一段时间内拥有该对象,则需要保留(retain)它并确保在操作完成时释放它。

(3)如果你保留(retain)了某个对象,你需要(最终)释放或自动释放该对象。必须保持retain方法和release方法的使用次数相等。

我的程序是iPhone程序,为了降低程序的内存空间占用,Cocoa在GUI应用程序中规定了自动释放池的销毁时间,在程序开始处理事件之前创建一个自动释放池,并在事件处理结束后销毁该自动释放池。我的localFiles对象在开始时创建了一个自动释放对象,完成之后进行下一个事件循环,自动释放池已经销毁,localFiles对象也就被释放了,在滚动tableView时进入下一个事件循环,所以localFiles对象的内容就找不到了。

分享到:
评论

相关推荐

    NSArray_NSMutableArray

    Objective-C的数组比C++,Java的数组强大在于,NSArray保存的对象可以是不同的对象。但只能保存对象,int ,char,double等基本数据类型不能直接保存,需要通过转换成对象才能加入数组。

    Iphone数组一些基础操作 NSArray/NSMutableArray

    然后通过`count`属性获取数组中对象的数量: ```objc NSLog(@"self.dataArray count:%d",[self.dataArray count]); ``` 以及使用`objectAtIndex:`方法获取指定索引处的对象: ```objc NSLog(@"self.dataArray count ...

    IOS 开发之 NSMutableArray与NSArray 的区别

    在 IOS 开发中,NSMutableArray 和 NSArray 是两个非常重要的集合类,它们都是 Foundation 框架的一部分。在本文中,我们将详细介绍 NSMutableArray 和 NSArray 的区别,并讨论它们的使用场景和优缺点。 一、 ...

    iphone 对象转字典 增强版

    "iPhone对象转字典增强版"针对的是Objective-C或Swift中的对象模型到字典的转化过程中遇到的问题,特别是处理数组和字典嵌套时的异常。在上一个版本中,可能存在数组和字典转换不完全或错误的情况,这个增强版应该对...

    NSMutableArray-SafeTransaction:NSMutableArray线程安全事务

    NSMutableArray-SafeTransaction NSMutableArray线程安全事务 NSMutableArray不是线程安全的,如果您向每个API添加锁定,则会被包围。... 线程#2删除最后一个对象。 线程#1访问count-1对象,然后引发异常。

    iOS 对NSMutableArray进行排序和过滤的实例

    在示例代码中,`ViewController`是一个简单的视图控制器,它持有一个`NSMutableArray`(`dataArray`),并添加了一些`TestBean`对象。`viewDidLoad`方法中创建了这些对象并添加到数组中。之后,通过调用`...

    Cocoa夜未央第四期-老jar

    - **概念**:内存自动释放池是一种机制,用于自动管理内存中对象的释放。 - **用途**:特别适用于生命周期较短的对象,例如临时变量。 - **实现**:通过`@autoreleasepool`块实现。 ```objective-c @...

    ios之内存管理

    5. **自动释放池**:在iOS中,每个RunLoop周期都会有一个自动释放池,用于收集并释放那些没有直接引用的对象。在自定义数组中,合理利用自动释放池可以有效地管理临时对象。 6. **避免野指针**:在释放数组或其元素...

    复制对象(一)copy和mutableCopy方法对应Demo

    浅复制和深复制是复制过程中两个重要的概念,它们关乎内存中对象引用的处理方式。 3. 浅复制(Shallow Copy): 浅复制是指创建一个新的对象,该对象拥有原始对象的属性值,但这些属性如果是引用类型,则指向的是...

    iOS内存管理1

    例如,NSMutableArray的mutableCopy方法可以创建一个浅拷贝,而深拷贝需要使用专门的方法来实现。 工具 instruments是iOS开发中一个非常有用的工具,可以用来检测内存泄露和循环引用。 iOS内存管理是一个非常复杂...

    NSMutableArray-Delegate

    NSMutableArray-Delegate 是为可变数组添加模式委托的类别。 支持的委托方法 - (void)mutableArray:(NSMutableArray *)array willAddObject:(id)object - (void)mutableArray:(NSMutableArray *)array didAddObject...

    ios内存管理之深浅拷贝

    当对象的引用计数变为0时,系统会自动释放该对象,以回收内存。`retain`操作是增加对象的引用计数,`release`则是减少引用计数。`autorelease`会在未来的某个时间点自动调用`release`。 接下来,我们进入主题——...

    IOS应用源码之Array.rar

    - 当数组不再需要时,释放数组也会自动释放其包含的所有对象。 9. **Swift中的Array** - 在Swift中,也有Array类型,但它与Objective-C的NSArray有所不同,Swift的Array是可变的,提供了更丰富的功能和更好的性能...

    ios中,sqlite数据库数据与实体自动绑定

    本篇文章将详细探讨如何在Objective-C中实现SQLite数据库数据与实体对象的自动绑定,类似于Java或C#中的反射机制。 首先,我们需要理解什么是实体绑定。在面向对象编程中,实体通常代表业务对象,如用户、订单等。...

    swift-iOS(OC)JSON转Model的脚本

    在iOS应用开发中,数据交换通常涉及到JSON格式的数据与应用程序中的Model对象之间的转换。Swift和Objective-C(OC)作为苹果平台的主要编程语言,都提供了多种方法来实现这一过程。本篇将详细介绍如何在Swift和...

    iOS笔试题031

    关于autoreleasepool,一个应用中可以创建任意多的自动释放池,没有明确的限制。系统会自动创建和销毁自动释放池,但如果需要更精确地控制对象的生命周期,可以在适当位置手动创建。 内存管理是iOS开发中的重要概念...

    iOS runtime 方式归解档,存储多对象

    在iOS开发中,数据持久化是一项重要的任务,用于将应用程序中的数据保存到设备上,以便在用户退出应用或设备重启后仍然可以访问。本篇主要探讨的是如何利用Objective-C的runtime机制来实现对象的归档(archiving)与...

    ios7 Foundation框架文档

    - `-(void)drain`: 显式地释放自动释放池中所有的对象。 ##### 3. NSBlockOperation类 - **概述**:`NSBlockOperation`类提供了一种方便的方法来创建和执行包含块的异步操作。这些操作可以被添加到`...

    iOS-面试宝典3.0.pdf

    每当一个对象被autorelease时,它会被加入到最近的自动释放池中。当该池被释放时,所有加入到该池的对象也会被释放。 ### 二十、Objective-C如何对内存管理的,说说你的看法和解决方法 Objective-C的内存管理机制...

Global site tag (gtag.js) - Google Analytics