重新创建 NSMutableArray 重新初始化后的内存
我有一个类模仿 UIImagePickerController
的行为,但有一些细微的差异。在我的课堂上,我只使用一个视图控制器,并在用户进行行/缩略图选择时用它来交换相册表视图和照片表视图。因此,导致我出现问题的事件顺序如下:
- 我选择一个相册
- 照片表视图加载,然后按后退按钮返回 相册表视图 相册
- 表视图加载
- 我选择了一个相册,现在触发了内存访问错误
我已经在 ivars 中实现了表视图和数组,如下所示:
@property (nonatomic, retain) UITableView *selectAnAlbumTableView, *selectAPhotoTableView;
@property (nonatomic, retain) NSMutableArray *albums, *photos;
@property (nonatomic, retain) ALAssetsGroup *album;
@property (nonatomic, retain) UIActivityIndicatorView *spinner;
相册表视图和照片表视图之间的一个区别是照片表视图每次用户选择相册时都会重新创建,这就是错误发生的地方。最初,“EXC_BAD_ACCESS”是在我删除表格视图时发生的,就像我在这里所做的那样:
[[self selectAPhotoTableView] removeFromSuperview];
[selectAPhotoTableView release];
selectAPhotoTableView = nil;
[photos release];
photos = nil;
我注意到错误发生在[照片发布]
处。照片是我存储放置在照片表格视图上的单元格中的所有缩略图按钮的数组。如果我删除 [photos release]
和 photos = nil,那么当实际创建表视图时就会出现问题(正如我最初提到的):
NSMutableArray *photosTemp = [[NSMutableArray alloc] init];
[self setPhotos: photosTemp];
[photosTemp release];
现在在 [ 之后抛出“EXC_BAD_ACCESS”自我设置Photos: photosTemp];
行。有谁知道我在这里做错了什么?
更新:我在第二次发生错误的位置输入了错误的代码,现在已修复。
I have a class that mimics the behavior of the UIImagePickerController
except with some subtle differences. In my class, I use only one view controller and use it to swap out the albums tableview and photos tableview when the user makes a row / thumbnail selection. So the sequence of events that is causing me problems is as follows:
- I select an album
- The photos tableview loads, and I push the back button to go back
to the albums tableview - The albums tableview loads
- I select an album, and now a memory access error triggers
I have implemented both of the tableviews and the array in ivars as follows:
@property (nonatomic, retain) UITableView *selectAnAlbumTableView, *selectAPhotoTableView;
@property (nonatomic, retain) NSMutableArray *albums, *photos;
@property (nonatomic, retain) ALAssetsGroup *album;
@property (nonatomic, retain) UIActivityIndicatorView *spinner;
One difference between the albums tableview and the photos tableview is that the photos tableview is recreated each time a user selects an album and this is where the error occurs. Initially, the "EXC_BAD_ACCESS" was occurring when I was removing the tableview, like I do here:
[[self selectAPhotoTableView] removeFromSuperview];
[selectAPhotoTableView release];
selectAPhotoTableView = nil;
[photos release];
photos = nil;
I noticed the error is occurring at [photos release]
. Photos is the array where I store all of the thumbnail buttons that are put in cells on the photos tableview. If I remove [photos release]
and photos = nil, then the problem occurs when the tableview is actually created (as I mentioned initially):
NSMutableArray *photosTemp = [[NSMutableArray alloc] init];
[self setPhotos: photosTemp];
[photosTemp release];
Now the "EXC_BAD_ACCESS" is being thrown after the [self setPhotos: photosTemp];
line. Does anyone know what I'm doing wrong here?
UPDATE: I put the wrong code for where the error occurs the second time, now it's fixed.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我会将其放在答案中而不是大量评论中。
这行(见评论)会导致一个问题:
那是因为
thumbnailImage
是一个ivar。UIImage imageWithCGImage
正在返回一个自动释放的对象。因此,您必须显式保留它,如下所示:或者,您可以让您的属性通过生成的设置器为您完成此操作。按如下方式设置属性不会执行任何操作,因为在上面的行中,您直接引用
thumbnailImage
,而不是通过设置器。你需要做的是使用
self
,所以你有:这将通过生成的setter,首先检查是否有任何现有对象,
release
如果有一个,然后执行aretain
您新分配的对象。所有这一切都是自动发生的。换句话说,它省去了你做这件事的麻烦:Aaron Hillegass 的书“Cocoa Programming for Mac OS X”对此内容有很好的解释。
要做的关键事情是使用分析器运行构建,或者只是不时运行分析器。在您开始追踪 EXC_BAD_ACCESS 错误的耗时过程之前,它会发现很多此类问题。
I'll put this in an answer rather than a massive comment.
This line (see comments) will cause a problem:
That's because
thumbnailImage
is an ivar.UIImage imageWithCGImage
is returning you an autoreleased object. Therefore you must retain it either explicitly, as follows:Or, you can let your property do it for you via the generated setters. Setting up a property as follows won't do anything because in your line above you are referring to
thumbnailImage
directly, not via the setters.What you need to do is use
self
, so you have:That will go through generated setters that first checking for any existing object,
release
it if there is one, then do aretain
on your newly assigned object. All that happens automatically. In other words, it saves you the bother of doing:Aaron Hillegass' book has a great explanation of this stuff in "Cocoa Programming for Mac OS X".
A key thing to do is to run builds with the Analyzer, or just run the Analyzer from time to time. It will spot a lot of these issues before you get to the time consuming process of tracking down EXC_BAD_ACCESS errors.
EXC_BAD_ACCESS 意味着您提供了一个无效的指针(在此上下文中,
nil
可以被视为“有效”)。在第一种情况下,错误的指针将显示为照片
。如果它是一个自动变量,它可能会很糟糕,因为你未能初始化它,但系统总是将实例变量清空。
因此,要么您为其分配了无效的内容,要么其中的值仍然存在,但它所寻址的对象已被释放。
第二种情况下的错误奇怪地表明“self”已被释放。这很可能是您的根本问题,并且您的
dealloc
方法正在释放photos
,因此首先会显示错误。我建议你在你的dealloc例程中放置一个NSLog,看看它是否被调用得太快,如果是这样,那么显然要弄清楚你是如何未能正确保留控制器对象的。EXC_BAD_ACCESS means that you presented a pointer that isn't valid (and in this context
nil
can be considered "valid"). In your first case that bad pointer would appear to bephotos
.If it were an auto variable it could be bad because you failed to initialize it, but the system always nulls instance variables.
So either you assigned something invalid to it, or the value that was in it is still there, but the object it addressed has been released.
The error in the second case is oddly suggesting that "self" has been released. This could well be your root problem, and your
dealloc
method is releasingphotos
, so that shows the error first. I'd suggest you place a NSLog in yourdealloc
routine to see if it's getting invoked too soon, and, if so, then obviously figure out how you failed to properly retain your controller object.