Что в моем коде вызывает эту ошибку (NSMutableArray является маленьким для вызываемого объекта)? - PullRequest
0 голосов
/ 19 августа 2011

Я предполагаю, что где-то в моем коде объекты в массиве удаляются быстрее, чем они создаются. Я искал проблему более часа, поэтому, пожалуйста, помогите!

Вот ошибка: *** 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];
    }
}

Ответы [ 3 ]

0 голосов
/ 19 августа 2011

Если вы добавите NSLog в метод animationEnded, подобный этому

- (void)animationEnded 
{   
    int av = [num intValue];
    NSLog(@"index => %i", av);

    // more stuff
}

. Вы увидите, что при каждом запуске будет выводиться наибольшее число, полученное в вашем цикле - 7.

Таким образом, первый раз при удалении объекта по индексу 7 все в порядке, но затем во второй раз вы снова удаляете индекс 7 при наличии только [0 .. 6] элементов

0 голосов
/ 19 августа 2011

Попытка вызвать метод в конце вашей анимации с таймером не рекомендуется. Вместо этого вы должны использовать метод класса 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:.

0 голосов
/ 19 августа 2011

В анимацииEnded вы пытаетесь удалить изображение # 7 7 раз, я полагаю.

РЕДАКТИРОВАТЬ: немного больше информации ...

Вы просматриваете каждое изображение (0 ... n) в moveObjs, повторно назначая 'num' в каждой итерации с новым значением.Таким образом, на последней итерации (которая, исходя из ошибки, я предполагаю, что i = 7, всего 8 изображений), num остается равным 7.

Когда анимация заканчивается, вызывается animationEnded,num превращается обратно в int (av), а элемент с индексом 'av' удаляется.

...