转自: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对象的内容就找不到了。
分享到:
相关推荐
Objective-C的数组比C++,Java的数组强大在于,NSArray保存的对象可以是不同的对象。但只能保存对象,int ,char,double等基本数据类型不能直接保存,需要通过转换成对象才能加入数组。
然后通过`count`属性获取数组中对象的数量: ```objc NSLog(@"self.dataArray count:%d",[self.dataArray count]); ``` 以及使用`objectAtIndex:`方法获取指定索引处的对象: ```objc NSLog(@"self.dataArray count ...
在 IOS 开发中,NSMutableArray 和 NSArray 是两个非常重要的集合类,它们都是 Foundation 框架的一部分。在本文中,我们将详细介绍 NSMutableArray 和 NSArray 的区别,并讨论它们的使用场景和优缺点。 一、 ...
"iPhone对象转字典增强版"针对的是Objective-C或Swift中的对象模型到字典的转化过程中遇到的问题,特别是处理数组和字典嵌套时的异常。在上一个版本中,可能存在数组和字典转换不完全或错误的情况,这个增强版应该对...
NSMutableArray-SafeTransaction NSMutableArray线程安全事务 NSMutableArray不是线程安全的,如果您向每个API添加锁定,则会被包围。... 线程#2删除最后一个对象。 线程#1访问count-1对象,然后引发异常。
在示例代码中,`ViewController`是一个简单的视图控制器,它持有一个`NSMutableArray`(`dataArray`),并添加了一些`TestBean`对象。`viewDidLoad`方法中创建了这些对象并添加到数组中。之后,通过调用`...
- **概念**:内存自动释放池是一种机制,用于自动管理内存中对象的释放。 - **用途**:特别适用于生命周期较短的对象,例如临时变量。 - **实现**:通过`@autoreleasepool`块实现。 ```objective-c @...
5. **自动释放池**:在iOS中,每个RunLoop周期都会有一个自动释放池,用于收集并释放那些没有直接引用的对象。在自定义数组中,合理利用自动释放池可以有效地管理临时对象。 6. **避免野指针**:在释放数组或其元素...
浅复制和深复制是复制过程中两个重要的概念,它们关乎内存中对象引用的处理方式。 3. 浅复制(Shallow Copy): 浅复制是指创建一个新的对象,该对象拥有原始对象的属性值,但这些属性如果是引用类型,则指向的是...
例如,NSMutableArray的mutableCopy方法可以创建一个浅拷贝,而深拷贝需要使用专门的方法来实现。 工具 instruments是iOS开发中一个非常有用的工具,可以用来检测内存泄露和循环引用。 iOS内存管理是一个非常复杂...
NSMutableArray-Delegate 是为可变数组添加模式委托的类别。 支持的委托方法 - (void)mutableArray:(NSMutableArray *)array willAddObject:(id)object - (void)mutableArray:(NSMutableArray *)array didAddObject...
当对象的引用计数变为0时,系统会自动释放该对象,以回收内存。`retain`操作是增加对象的引用计数,`release`则是减少引用计数。`autorelease`会在未来的某个时间点自动调用`release`。 接下来,我们进入主题——...
- 当数组不再需要时,释放数组也会自动释放其包含的所有对象。 9. **Swift中的Array** - 在Swift中,也有Array类型,但它与Objective-C的NSArray有所不同,Swift的Array是可变的,提供了更丰富的功能和更好的性能...
本篇文章将详细探讨如何在Objective-C中实现SQLite数据库数据与实体对象的自动绑定,类似于Java或C#中的反射机制。 首先,我们需要理解什么是实体绑定。在面向对象编程中,实体通常代表业务对象,如用户、订单等。...
在iOS应用开发中,数据交换通常涉及到JSON格式的数据与应用程序中的Model对象之间的转换。Swift和Objective-C(OC)作为苹果平台的主要编程语言,都提供了多种方法来实现这一过程。本篇将详细介绍如何在Swift和...
关于autoreleasepool,一个应用中可以创建任意多的自动释放池,没有明确的限制。系统会自动创建和销毁自动释放池,但如果需要更精确地控制对象的生命周期,可以在适当位置手动创建。 内存管理是iOS开发中的重要概念...
在iOS开发中,数据持久化是一项重要的任务,用于将应用程序中的数据保存到设备上,以便在用户退出应用或设备重启后仍然可以访问。本篇主要探讨的是如何利用Objective-C的runtime机制来实现对象的归档(archiving)与...
- `-(void)drain`: 显式地释放自动释放池中所有的对象。 ##### 3. NSBlockOperation类 - **概述**:`NSBlockOperation`类提供了一种方便的方法来创建和执行包含块的异步操作。这些操作可以被添加到`...
每当一个对象被autorelease时,它会被加入到最近的自动释放池中。当该池被释放时,所有加入到该池的对象也会被释放。 ### 二十、Objective-C如何对内存管理的,说说你的看法和解决方法 Objective-C的内存管理机制...