我假设在我的代码中的某个地方,数组中的对象被删除的速度比创建它们的速度快。我一直在寻找这个问题超过一个小时所以请帮忙!
以下是错误:*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSMutableArray objectAtIndex:]: index 7 beyond bounds [0 .. 6]'
在此先感谢,这是我的代码:
- (void)onTimer {
UIImageView *imgView = [[UIImageView alloc] init];
imgView.image = particleImg;
imgView.frame = CGRectMake(kViewDimensions/2, kViewDimensions/2, startSize.width, startSize.height);
[self addSubview:imgView];
[particlesArray addObject:imgView];
[imgView release];
moveTimer = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector(moveObjs) userInfo:nil repeats:YES];
}
- (void)moveObjs {
for (int i = 0; i < [particlesArray count]; i++) {
animID = @"MoveId";
UIImageView *imgV = [particlesArray objectAtIndex:i];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3];
CGPoint randPoint = CGPointMake(arc4random()%kMaxRandX, arc4random()%kMaxRandY);
imgV.center = CGPointMake(randPoint.x, randPoint.y);
[UIView commitAnimations];
animValue = i;
num = [NSNumber numberWithInt:animValue];
[NSTimer scheduledTimerWithTimeInterval:0.3 target:self selector:@selector(animationEnded) userInfo:num repeats:NO];
NSLog(@"\n %d",animValue);
}
}
- (void)animationEnded {
int av = [num intValue];
UIImageView *iv = [particlesArray objectAtIndex:av];
if ([animID isEqualToString:@"MoveId"]) {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.1];
iv.alpha = 0.0f;
[UIView commitAnimations];
[particlesArray removeObjectAtIndex:av];
}
else {
[iv removeFromSuperview];
}
}
答案 0 :(得分:0)
在animationEnded中,你试图删除图片#7 7次,我相信。
编辑:更多信息......
循环遍历moveObjs中的每个图像(0 ... n),在每次迭代中使用新值重新分配'num'。所以在最后一次迭代中(基于错误,我假设i = 7,总共8个图像),num保留在7。
当动画结束时,调用animationEnded,将num转回int(av),并删除索引'av'处的元素。
答案 1 :(得分:0)
如果您在NSLog
方法中添加animationEnded
,就像这样
- (void)animationEnded
{
int av = [num intValue];
NSLog(@"index => %i", av);
// more stuff
}
您将看到,对于每次运行,它将注销由循环产生的最高数字,即7。
所以第一次在索引7处移除对象是正常的,但是当第二次在仅有[0 .. 6]项时再次移除索引7时
答案 2 :(得分:0)
尝试使用计时器在动画结束时触发方法是不明智的。相反,您应该在动画块中使用setAnimationDidStopSelector:
类方法。最重要的是,由于您使用num来处理从数组中删除对象的方式,因此您可以保证在animationEnded的一个调用期间的某个时刻超过数组的边界。最好引用对象本身,而不是它在数组中的位置。这就是beginAnimations:context:
方法中的上下文参数的用途:
- (void)moveObjs {
for (int i = 0; i < [particlesArray count]; i++) {
animID = @"MoveId";
UIImageView *imgV = [particlesArray objectAtIndex:i];
[UIView beginAnimations:nil context:imgV];
[UIView setAnimationDuration:0.3];
[UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
CGPoint randPoint = CGPointMake(arc4random()%kMaxRandX, arc4random()%kMaxRandY);
imgV.center = CGPointMake(randPoint.x, randPoint.y);
[UIView commitAnimations];
}
}
- (void)animationDidStop:(NSString *)animID finished:(NSNumber *)finished context:(void *)context {
UIImageView *iv = (UIImageView *)context;
if ([animID isEqualToString:@"MoveId"]) {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.1];
iv.alpha = 0.0f;
[UIView commitAnimations];
[particlesArray removeObject:iv];
} else {
[iv removeFromSuperview];
}
}
注意:如果您不支持iOS 4之前的版本,则应切换到使用基于块的新方法,例如animateWithDuration:animations:completion:
。