Проблема NSTimer в Objective-C - PullRequest
       13

Проблема NSTimer в Objective-C

0 голосов
/ 21 сентября 2011

Я работаю над приложением Kid's Book для iPad.Он имеет UIView, который загружает UIImageView для отображения UIImages (JPEG), пользователь может пролистывать изображения для просмотра страниц.Я также добавил некоторую интерактивность на некоторые страницы, добавив еще один UIImageView, который загружал бы файл PNG, и на жесте касания я их анимировал.На одной из страниц у меня есть анимация падения листьев на экран (стр. 10), и я использую для этого NSTimer, он работает нормально, однако, когда я провожу пальцем и перехожу на следующую страницу, анимация все еще происходит.Я хочу, чтобы анимация запускалась ТОЛЬКО на стр. 10, и должна немедленно прекратиться, если я перейду на стр. 9 (пролистывание назад) или на стр. 11 (пролистывание вперед).Я попытался поставить условие (if (pageNum == 10)), и оно останавливается через несколько секунд, поэтому я все еще вижу несколько листов, падающих на предыдущие / пересылки страниц.Думаю, я понимаю, почему это происходит, но не знаю, как это исправить.Ниже приведен фрагмент кода:

- (void)handleTap:(UITapGestureRecognizer *)recognizer {
    NSLog(@"ChildrenBookViewController ==> handleTap.");
    switch (((UIGestureRecognizer *)recognizer).view.tag)      
    {
        case 1:
            //Some animation for Page 1
            break;
        case 2:
            //Some animation for Page 2
            break;
        //....
        case 10:
            // load our leaf image we will use the same image over and over
            leafImage = [UIImage imageNamed:@"leaf_small.png"];
            // start a timet that will fire 20 times per second
            timer = [NSTimer scheduledTimerWithTimeInterval:(0.05) target:self selector:@selector(onTimer) userInfo:nil repeats:YES];
            break;
        case 11:
            //Some animation for Page 11
            break;
        default:
            NSLog(@"ChildrenBookViewController ==> handleTap. Switch Case: DEFAULT");
            break;
    }
}

// Timer event is called whenever the timer fires
- (void)onTimer
{
    if (pageNum == 10)
    {
        // build a view from our leaf image
        UIImageView* leafView = [[UIImageView alloc] initWithImage:leafImage];

        // use the random() function to randomize up our leaf attributes
        int startX = round(random() % 1024);
        int endX = round(random() % 1024);
        double scale = 1 / round(random() % 100) + 1.0;
        double speed = 1 / round(random() % 100) + 1.0;

        // set the leaf start position
        leafView.frame = CGRectMake(startX, -100.0, 25.0 * scale, 25.0 * scale);
        //leafView.alpha = 0.25;

        // put the leaf in our main view
        [self.view addSubview:leafView];

        [UIView beginAnimations:nil context:leafView];
        // set up how fast the leaf will fall
        [UIView setAnimationDuration:5 * speed];

        // set the postion where leaf will move to
        leafView.frame = CGRectMake(endX, 500.0, 25.0 * scale, 25.0 * scale);

        // set a stop callback so we can cleanup the leaf when it reaches the
        // end of its animation
        [UIView setAnimationDidStopSelector:@selector(onAnimationComplete:finished:context:)];
        [UIView setAnimationDelegate:self];
        [UIView commitAnimations];
    }else{
        if (timer) {
            [timer invalidate];
            timer = nil;
        }
    }
}
- (void)onAnimationComplete:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
    UIImageView *leafView = context;
    [leafView removeFromSuperview];
    [leafView release]; 
}

1 Ответ

1 голос
/ 21 сентября 2011

Вместо того, чтобы аннулировать таймер в методе onTimer, вы должны сделать его недействительным в обратном вызове, установленном для случаев смахивания (изменение страниц) на страницах 9 и 11.Таким образом, таймер станет недействительным, как только пользователь проведет пальцем для переключения страниц.

РЕДАКТИРОВАТЬ: Как заметил @Alex, это только остановит запрос дополнительных анимаций, но уже запущенный будет продолжен... Я предполагаю, что у вас есть ссылка на leafView, поэтому вы должны позвонить

[leafView.layer removeAllAnimations], а затем удалить его из суперпредставления или скрыть его или что угодно ...

...