重新创建NSMutableArray后重新初始化内存

时间:2011-10-19 17:41:25

标签: iphone ios cocoa-touch uiview uiviewcontroller

我有一个模仿UIImagePickerController行为的类,除了一些微妙的差异。在我的班级中,我只使用一个视图控制器,并在用户进行行/缩略图选择时使用它来换出相册tableview和照片tableview。因此导致我出现问题的事件顺序如下:

  1. 我选择了一张专辑
  2. 照片tableview加载,我按后退按钮返回 到相册tableview
  3. 相册tableview加载
  4. 我选择了一个相册,现在发生内存访问错误
  5. 我已经在ivars中实现了tableviews和数组,如下所示:

    @property (nonatomic, retain) UITableView *selectAnAlbumTableView, *selectAPhotoTableView;
    @property (nonatomic, retain) NSMutableArray *albums, *photos;
    @property (nonatomic, retain) ALAssetsGroup *album;
    @property (nonatomic, retain) UIActivityIndicatorView *spinner;
    

    相册tableview和照片tableview之间的一个区别是每次用户选择相册时都会重新创建照片tableview,这就是错误发生的地方。最初,当我删除tableview时发生了“EXC_BAD_ACCESS”,就像我在这里一样:

            [[self selectAPhotoTableView] removeFromSuperview];
            [selectAPhotoTableView release];
            selectAPhotoTableView = nil;
            [photos release];
             photos = nil;
    

    我注意到错误发生在[photos release]。照片是我存储放在照片桌面视图中的单元格中的所有缩略图按钮的数组。如果我删除了[photos release]和photos = nil,那么当实际创建tableview时会出现问题(正如我最初提到的那样):

    NSMutableArray *photosTemp = [[NSMutableArray alloc] init];
    [self setPhotos: photosTemp];
    [photosTemp release];
    

    现在在[self setPhotos: photosTemp];行之后抛出“EXC_BAD_ACCESS”。有谁知道我在这里做错了什么?

    更新:我第二次把错误的代码放在错误发生的位置,现在已经修复了。

2 个答案:

答案 0 :(得分:1)

我会把这个放在答案而不是大量评论中。

此行(请参阅注释)会导致问题:

thumbnailImage = [UIImage imageWithCGImage:[theALAsset thumbnail]]; 

那是因为thumbnailImage是一个ivar。UIImage imageWithCGImage正在返回一个自动释放的对象。因此,您必须明确地保留它,如下所示:

thumbnailImage = [[UIImage imageWithCGImage:[theALAsset thumbnail]] retain]; 

或者,您可以通过生成的设置者让您的财产为您完成。如下设置属性将不起作用,因为在上面的行中,您直接引用thumbnailImage,而不是通过设置者。

@property (nonatomic, retain) UIImage *thumbnailImage;

您需要做的是使用self,因此您拥有:

self.thumbnailImage = [UIImage imageWithCGImage:[theALAsset thumbnail]]; 

这将通过首先检查任何现有对象的生成的setter,release如果有的话,然后在新分配的对象上执行retain。一切都是自动发生的。换句话说,它可以省去你的麻烦:

-(void)setThumbnailImage:(UIImage *)aThumbnailImage
{
    [aThumbnailImage retain];
    if (thumbnailImage)
    {
        [thumbnailImage release];
    }
    thumbnailImage = aThumbnailImage;
}

Aaron Hillegass的书在“Mac OS X的可可编程”中对这些内容有很好的解释。

要做的一件事是使用Analyzer运行构建,或者只是不时运行Analyzer。在您进入追踪EXC_BAD_ACCESS错误的耗时过程之前,它会发现很多这些问题。

答案 1 :(得分:0)

EXC_BAD_ACCESS表示您提供的指针无效(在此上下文中nil可被视为“有效”)。在第一种情况下,坏指针似乎是photos

如果它是一个自动变量,它可能会很糟糕,因为你无法初始化它,但系统总是使实例变量为空。

所以要么你给它分配了一些无效的东西,要么它里面的值仍然存在,但它所解决的对象已被释放。

第二种情况中的错误奇怪地暗示“自我”已被释放。这可能是您的根本问题,并且您的dealloc方法正在发布photos,因此首先显示错误。我建议你在你的dealloc例程中放置一个NSLog来查看它是否过早被调用,如果是这样的话,那么显然可以找出你未能正确保留控制器对象的方法。