开发者

Crash after animateWithDuration because of bad access

开发者 https://www.devze.com 2023-03-02 04:17 出处:网络
Please see the below 开发者_开发知识库code. It shows animation effect with image. UIImageView *imgView = [[UIImageView alloc] initWithImage:img];// ref count = 1

Please see the below 开发者_开发知识库code. It shows animation effect with image.

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?
}];

From the above code, if I remove [imgView release] there is no crash. but, the above code makes crash from the completion routine. Why? As I think reference count changed as like the comment. Then there should be no crash.

Could you please explain why the completion routine makes crash?


OK. I solved my problem. In fact, problem was not in the code I showed. There was no problem in this code.

The reason of crash is related with 'img' object which is used as initial argument of UIImageView. Actually, I accidentally released it one more time from the other place.

I think when UIImageView object deallocated it try to release it's Image object. But, it's already deallocate so, crash happend. It just looks like [imgView removeFromSuperview] makes crash.

Sorry for fuss.


Here is my two cents: Once you release imgView (//ref count = 1) that variable no longer contains a reference to your object. If you plan on using it further ahead, like I see you are doing with the animation, you should release it afterwards. Hope this helps.


Although the image view is still referenced by the view which you've added it to, you don't have any references to it. Once you call [imgView release], before the animate block, you've lost all of your references to the image view. The rule of thumb is that every alloc, copy, and retain requires a matching release or autorelease. Although the overlayView internally retains a reference to the view, you did not retain it anywhere, so as soon as you release it, it's gone.

I suggest autoreleasing the UIImageView instead. (Or, you may be able to put the release in the completion handler.)

Sample Code:

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]; 
}];

EDIT:

You can try changing [imageView removeFromSuperview]; to:

if(imageView){
  [imageView removeFromSuperview];
}
0

精彩评论

暂无评论...
验证码 换一张
取 消