UIButton IBAction方法只绘制一次屏幕?

时间:2012-12-11 16:18:32

标签: iphone objective-c cocoa-touch uibutton

我对一些我只是为了好玩而尝试的东西感到有些困惑。我编写了一个名为animateBars_V1的小方法,该方法使用UIImageViews数组并改变每个UIImageView的高度,以显示一组不断变化的彩色条。

enter image description here

- (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_V1 5次。发生的事情是,直到循环退出后,条形才会改变。这导致:

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

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

3 个答案:

答案 0 :(得分: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];
}

答案 1 :(得分: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);
    }
}

答案 2 :(得分:0)

问题出在这里

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

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

<强>被修改 删除了睡眠呼叫,因为它将睡眠主线程,一切都将停止。所以在这里使用Timer