1

我对我只是为了好玩而尝试的事情有点困惑。我编写了一个小方法animateBars_V1,它使用 UIImageViews 数组并更改每个 UIImageView 的高度以显示一组不断变化的彩色条。

在此处输入图像描述

- (void)animateBars_V1 {
    srandom(time(NULL));
    for(UIImageView *eachImageView in [self barArray]) {
        NSUInteger randomAmount = kBarHeightDefault + (random() % 100);

        CGRect newRect;
        CGRect barRect = [eachImageView frame];

        newRect.size.height = randomAmount;
        newRect.size.width = barRect.size.width;
        newRect.origin.x = barRect.origin.x;
        newRect.origin.y = barRect.origin.y - (randomAmount - barRect.size.height);
        [eachImageView setFrame:newRect];
    }
}

这很好用,然后我添加了一个带有 UIAction 的 UIButton 用于按下按钮时。每次按下按钮时,animateBars_V1都会调用该按钮并更新彩条。

- (IBAction)buttonPressed {
    for(int counter = 0; counter<5; counter++) {
        [self animateBars_V1];
        NSLog(@"COUNTER: %d", counter);
    }
}

我的问题只是为了好玩,我决定每次按下按钮我都会调用animateBars_V15 次。发生的情况是,直到循环退出之后,条形才会改变。这导致:

Screen as per storyboard
COUNTER: 0
COUNTER: 1
COUNTER: 2
COUNTER: 3
COUNTER: 4
Screen Updates

这是正确的行为吗?我不需要修复或解决方法,因为这只是为了好玩,我更好奇发生了什么以供将来参考。

4

3 回答 3

4

如果您animateBars_V1在循环中多次调用,则条形的帧会被设置多次,但在它们可以被渲染之前,animateBars_V1再次被调用,并且帧被设置为新的位置/大小。

drawRect:直到循环完成后才会调用渲染(和相关方法) - 因为它是一个 IBAction,所以必须在主线程中调用它,这意味着所有渲染都被阻塞,直到代码完成。

当然,有几种解决方案。做多动画的一个简单方法是UIView animateWithDuration:animations:completion:按以下方式使用:

- (IBAction)buttonPressed {
    [self animateBarsWithCount:5];
}

- (void)animateBarsWithCount:(int)count
{
    [UIView animateWithDuration:.25f animations:^{
        [self animateBars_V1];
    }completion:^(BOOL finished){
        [self animateBarsWithCount:count - 1];
    }];
}

//animateBars_V1 not repeated

当然,如果你只是想运行一次动画,(但实际上是动画)你应该这样做:

- (IBAction)buttonPressed {
    [UIView animateWithDuration:.25f animations:^{
        [self animateBars_V1];
    } completion:nil];
}
于 2012-12-11T16:22:52.563 回答
2

CrimsonDiego 是对的

您可以尝试通过以下方式延迟每次通话:

- (IBAction)buttonPressed {
    for(int counter = 0; counter<5; counter++) {
        float ii = 1.0 * counter / 10;
        [self performSelector:@selector(animateBars_V1) withObject:nil afterDelay:ii];
        //  [self animateBars_V1];
        NSLog(@"COUNTER: %d", counter);
    }
}
于 2012-12-11T16:31:59.630 回答
0

问题就在这里

for(int counter = 0; counter<5; counter++) {
    [self animateBars_V1];
    NSLog(@"COUNTER: %d", counter);
}

这个 for 循环在纳秒内执行,您的眼睛无法赶上这种变化,因为眼睛只能检测到 1/16 秒。用于测试什么可以在运行五次的计时器中运行此代码。

编辑 删除了睡眠调用,因为它将使主线程睡眠并且一切都将停止。所以在这里使用 Timer

于 2012-12-11T16:29:16.653 回答