为什么我的NSArray被解除分配?

时间:2012-10-08 12:03:58

标签: objective-c ios automatic-ref-counting

我正在尝试理解自动引用计数,因为我来自高级编程语言(Python),我正在开发一个使用Objective-C的这个功能的项目。我常常遇到ARC解除分配对象的问题,我稍后需要这些问题,但现在我得到了一个具体的例子,希望我能得到解释。

- (void) animateGun:(UIImageView *)gun withFilmStrip:(UIImage *)filmstrip{
  NSMutableArray *frames = [[NSMutableArray alloc] init];
  NSInteger framesno = filmstrip.size.width / gun_width;
  for (int x=0; x<framesno; x++){
    CGImageRef cFrame = CGImageCreateWithImageInRect(filmstrip.CGImage, CGRectMake(x * gun_width, 0, gun_width, gun_height));
    [frames addObject:[UIImage imageWithCGImage:cFrame]];
    CGImageRelease(cFrame);
  }
  gun.image = [frames objectAtIndex:0];
  gun.animationImages = frames;
  gun.animationDuration = .8;
  gun.animationRepeatCount = 1;
  [gun startAnimating];
  dispatch_after(dispatch_time(DISPATCH_TIME_NOW,(arc4random() % 300)/100 * NSEC_PER_SEC), dispatch_get_current_queue(),^{
    [self animateGun:leftGun withFilmStrip:[self getFilmStripForAction:gunShoot andTeam:nil withWeapon:nil]];
  });
}

这段代码背后的想法很简单:我有(UIImageView*)gun我随机时间使用(NSMutableArray *)frames中存储的图像制作动画。 (UIImage *)filmstrip只是一个包含将在动画中使用的所有帧的图像。动画的第一次迭代有效,但问题出现在第二次迭代中,我得到-[UIImage _isResizable]: message sent to deallocated instance ...-[UIImage _contentStretchInPixels]: message sent to deallocated instance ...-[NSArrayI release]: message sent to deallocated instance ...。这发生在

gun.animationImages = frames;

但我不明白为什么。我不是要求解决我的问题,而只是为了帮助我理解这里发生的事情。感谢。

2 个答案:

答案 0 :(得分:0)

ARC是一种无需手动保留/释放对象的机制。这是一个很好的网站,解释了它的工作原理:http://longweekendmobile.com/2011/09/07/objc-automatic-reference-counting-in-xcode-explained/

尝试将“leftGun”更改为“gun”。如果你通过ivar使用它,我认为这可能是在某些时候被解除分配的那个。否则,leftGun根本不在范围内。

这是它应该是什么样子:

在你的.h文件中:

@property (nonatomic, strong) IBOutlet UIImageView *leftGun;

在您的.m文件中:

  dispatch_after(dispatch_time(DISPATCH_TIME_NOW,(arc4random() % 300)/100 * NSEC_PER_SEC), dispatch_get_current_queue(),^{
    [self animateGun:gun withFilmStrip:[self getFilmStripForAction:gunShoot andTeam:nil withWeapon:nil]];
  });

另外,不太确定“gunShoot”的来源。这应该是一个枚举吗?

修改

添加了如何定义leftGun属性的示例。在ivar上使用属性的原因是出于内存管理的目的。如果要释放或销毁作为属性的对象,只需将其设置为nil,如果必须,属性将负责释放对象。

答案 1 :(得分:-1)

如果您将frames数组标记为__block,则可以阻止重新分配。

  __block NSMutableArray *frames = [NSMutableArray array];

请参阅“The __block Storage Type.”