tableView:moveRowAtIndexPath:toIndexPath:看内存管理
来源:互联网 发布:centos 7 minimal ssh 编辑:程序博客网 时间:2024/05/20 11:33
/*今天本来在研究tableView:moveRowAtIndexPath:toIndexPath:这个方法,但是一个crash,让我有了一些有意思的发现,从而让我对内存管理有了更深的认识,不过这些只是我的个人理解,或许不正确,希望大家看过以后也可以发表一下意见*/
首先我就直接上一段代码
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{
NSInteger fromRow = [sourceIndexPath row];
NSInteger toRow = [destinationIndexPath row];
id obj = [self.mArrobjectAtIndex:fromRow];
//NSLog(@"%d,%p",[obj retainCount],obj);--------------1
//NSLog(@"%p",[self.mArr objectAtIndex:fromRow]);-----2
//[obj retain];---------------------------------------3
//NSLog(@"%d",[obj retainCount]);---------------------4
[self.mArrremoveObjectAtIndex:fromRow];
//NSLog(@"%d",[obj retainCount]);---------------------5
//NSLog(@"%d",[obj retainCount]);---------------------6
//NSLog(@"%p",obj);-----------------------------------7
if (destinationIndexPath.row > [self.mArrcount])
{
[self.mArraddObject:obj];
//NSLog(@"%d",[obj retainCount]);-----------------8
}
else
{
//NSLog(@"%d",[obj retainCount]);-----------------9
[self.mArrinsertObject:obj atIndex:toRow];
//NSLog(@"%d,%p",[obj retainCount],obj);---------10
}
//[self.mArr insertObject:obj atIndex:toRow];--------11
//[obj release];-------------------------------------12
//NSLog(@"%d",[obj retainCount]);--------------------13
}
将上面代码的3与12打开则不会发生崩溃。
其他是暴力调试用的,可以尝试打开它们,自己调试,会发现有意思的现象。在这里我简单说一下我的发现。
首先,将第1句与第2句打开,从打印结果你会发现,obj与[self.mArr objectAtIndex:fromRow]是同一个对象。
然后只打开1,5,10并且保持两个retain,release语句关闭时,你会发现打印的引用计数的结果为1,1,2。
但是,如果打开两个retain,release语句,并且打开它们相应的引用计数语句,也就是打开1,3,4,5,10,12,13;这时打印的引用计数的结果为1,2,1,2,1。
好玩的事情发生了,就是在经过[self.mArr removeObjectAtIndex:fromRow]语句后,第一种情况的引用计数并没有减少,仍是1,而第二种情况的引用计数却由2降为1,我就很纳闷,这是什么情况,所以添加了语句9,因为我怀疑可能只是当时引用计数并未减少,而是在之后又进行了减少,这时出现了预料中的结果,在打断点的情况下,清楚地看到程序是在执行第9句的时候崩溃了,也就是说在这里obj的引用计数已经变为0,被清除了,所以才会引发crash,但是为什么不在第5句的时候就崩溃呢?为了排除其他想不到的因素,我在语句5后紧跟着添加了语句6,运行,哎?这次崩在了第6句,于是我大胆猜测,苹果可能由于某种原因设计了一种机制,就是在对象被某种方式使引用计数降为0以后,仍暂时保留它,直到下次调用以后,再清除。不过,这些只是我在自己现有的水平下的臆测,也希望知道其中原委的人解决我的疑惑。(补充:当我将第1句引去,则不会在第6句发生崩溃,第9句也不会崩溃,只在第二次移动同一句时,产生崩溃,这推翻了我的猜测,也加深了我的疑惑)。
没移动前移动一次再次移动同一标号行产生了崩溃。
这个事情让我重新审视了内存管理的法则。附在最后
1,当你使用new、alloc、或copy方法创建一个对象时,该对象的保留计数器值为1.当不再使用该对象时,你要负责向该对象发送一条release或autorelease消息。这样,该对象将在其使用寿命结束时被销毁。
2当你通过任何其他方法获得一个对象时,则假设该对象的保留计数器值为1,而且已经被设置为自动释放,你不需要执行任何操作来确保该对象被清理。如果你打算在一段时间内拥有该对象,则需要保留它并确保在操作完成时释放它。
3如果你保留了某个对象,你需要(最终)释放或自动释放该对象。必须保持retain方法和release方法的使用次数相等(法则引自小橘子书)
- tableView:moveRowAtIndexPath:toIndexPath:看内存管理
- iOS关于TableView的moveRowAtIndexPath相关介绍
- 看nginx内存管理的一些感想
- Objective-C 内存管理 看这个就够啦
- moveRowAtIndexPath beginupdates 不更新
- 从物理页面的争抢看linux内核内存管理
- 从物理页面的争抢看linux内核内存管理
- OC属性与内存管理(二),初学者必看
- OC属性与内存管理(二),初学者必看
- C++ 测量程序运行时间 任务管理看内存
- Block的内存管理,看这里就够了
- UITableView的moveRowAtIndexPath的代码
- tableView中的一些问题-新手必看
- iOS-tableView联动你就看我
- 从C#中关于arraylist的引用看C#的内存管理
- windows内存管理1(做双缓存透明加密驱动必看)
- windows内存管理2(做双缓存透明加密驱动必看)
- 内存管理看全局变量、静态全局变量、局部变量、静态局部变量
- java加解密
- new、delete是使用
- IT 职场: 怎么样做好工作计划总结
- Android开源项目
- 山东理工大学ACM平台题答案关于C语言 1597 最大距离
- tableView:moveRowAtIndexPath:toIndexPath:看内存管理
- 中国金融、外汇开放与否?
- NYOJ 111 分数加减法
- 利用定时任务实现嵌入式下网卡状态检测
- 回波损耗、反射系数、电压驻波比以及S参数的物理意义
- Union 和 Union all
- Selenium-Webdriver(python) (十) --- 下拉框的选择
- php中文乱码
- [反省日记] 第一天