【问题标题】:Crash after animateWithDuration because of bad access由于访问不正确,在 animateWithDuration 后崩溃
【发布时间】:2011-08-15 14:29:07
【问题描述】:

请看下面的代码。用图片显示动画效果。

UIImageView *imgView = [[UIImageView alloc] initWithImage:img];  // ref count = 1
int offX = imgView.frame.size.width / 6;
int offY = (imgView.frame.size.height - 44) / 6;
imgView.frame = CGRectMake(offX, offY, imgView.frame.size.width - offX * 2, 
                           (imgView.frame.size.height - 44) - offY * 2);
[overlayView addSubview:imgView];  // ref count = 2
[imgView release];  // ref count = 1
[UIView animateWithDuration:1.0 animations:^{
    [imgView setCenter:CGPointMake(TRASH_X, TRASH_Y)];
    [imgView setTransform:CGAffineTransformMakeScale(0.1, 0.1)];
    [imgView setAlpha:0.5];
} completion:^(BOOL finished) {
    [imgView removeFromSuperview]; // ref count = 0? destroy imgView object?
}];

从上面的代码中,如果我删除 [imgView release] 没有崩溃。但是,上面的代码使完成例程崩溃。为什么?我认为引用计数的变化就像评论一样。那么应该不会崩溃。

您能解释一下为什么完成例程会崩溃吗?

【问题讨论】:

标签: iphone animation crash block


【解决方案1】:

这是我的两分钱:一旦您释放 imgView (//ref count = 1),该变量不再包含对您的对象的引用。如果您打算进一步使用它,就像我看到您正在使用动画一样,您应该在之后发布它。希望这会有所帮助。

【讨论】:

  • 抱歉,这不是正确的假设。将视图添加到它的超级视图后,它由超级视图保留。因此,在调用 removeFromSuperview 之前释放并使用它是没有问题的。
【解决方案2】:

尽管图像视图仍被您添加到的视图所引用,并没有对它的任何引用。一旦你在动画块之前调用[imgView release],你就失去了对图像视图的所有引用。经验法则是每个alloccopyretain 都需要匹配的releaseautorelease。尽管overlayView 内部保留了对视图的引用,但您并没有在任何地方retain 它,所以一旦您释放它,它就消失了。

我建议改为自动释放 UIImageView。 (或者,您可以将 release 放在完成处理程序中。)

示例代码:

UIImageView *imgView = [[[UIImageView alloc] initWithImage:img] autorelease];  
int offX = imgView.frame.size.width / 6;
int offY = (imgView.frame.size.height - 44) / 6;
imgView.frame = CGRectMake(offX, offY, imgView.frame.size.width - offX * 2, 
                           (imgView.frame.size.height - 44) - offY * 2);
[overlayView addSubview:imgView]; 
[UIView animateWithDuration:1.0 animations:^{
    [imgView setCenter:CGPointMake(TRASH_X, TRASH_Y)];
    [imgView setTransform:CGAffineTransformMakeScale(0.1, 0.1)];
    [imgView setAlpha:0.5];
} completion:^(BOOL finished) {
    [imgView removeFromSuperview]; 
}];

编辑:

您可以尝试将[imageView removeFromSuperview]; 更改为:

if(imageView){
  [imageView removeFromSuperview];
}

【讨论】:

  • 谢谢。但是,我已经尝试过这种方式,结果是一样的。崩溃了。
  • 你可以使用断点来精确定位崩溃发生的位置吗?
  • 摩西。即使 imageView 为零。向它发送消息应该没有问题。如您所知,向 nil 发送消息只是从 Objective C 中什么也不做。请参阅我自己的答案。顺便说一句 - 感谢您的帮助。
  • 如果您有 BAD ACCESS 问题,即使您检查“if (imageView)”,您也会被迷住。如果 imageView 在完成时被释放,任何读取其值的尝试都将导致 BAD ACCESS。
【解决方案3】:

好的。我解决了我的问题。 事实上,问题不在我展示的代码中。这段代码没有问题。

崩溃的原因与用作 UIImageView 的初始参数的 'img' 对象有关。其实我不小心又从别的地方放了一次。

我认为当 UIImageView 对象被释放时,它会尝试释放它的 Image 对象。但是,它已经解除分配,所以发生了崩溃。看起来 [imgView removeFromSuperview] 会导致崩溃。

抱歉打扰了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-02
    • 1970-01-01
    • 2015-01-21
    • 2011-04-20
    • 1970-01-01
    相关资源
    最近更新 更多