在循环中交换UIImageView图像

时间:2009-02-05 18:54:02

标签: cocoa-touch

我有一个UIImageViews的NSArray,我想循环并快速换出“开”和“关”状态。我在for循环中编写了代码,而不是在用户点击UIButton(按钮的动作)时调用的方法。

这是循环:

for(int i = 0; i < [Images count]; i++) {
    if( i > 0 ){
        [self toggleImageViewOff:[Images objectAtIndex:i - 1]];
    }

    [self toggleImageViewOn:[Images objectAtIndex:i]];

    [NSThread sleepForTimeInterval:0.5f];
}

UI没有像我预期的那样更新,因为我只看到了处于“开启”状态的最后一个UIImageView。我认为视图的绘图更新必须发生在这个代码也在执行的主线程中。所以我学习了performSelectorInBackground:withObject :.使用此方法执行toggleImageViewOn / Off方法使循环工作。问题是如果我将睡眠间隔设置得太短,我可以在“关闭”之后进行“开启”更新,并且线程无序运行。

所以我有一个明智的想法,即将整个循环与sleep一起移动到它自己的方法中,然后使用performSelectorInBackground:withObject:从action方法调用它。我试过了,在循环结束之前我回到了没有获得更新的视图。

这是一个冗长的方式来回答我的问题:

设置动画的最佳方法是什么,以保证开/关代码以正确的顺序触发,即使在高速运行时仍可获得视图更新? (即很快循环)

我试着想一想我是如何用CoreAnimation做的,但我似乎无法理解如何在那里做到这一点。

对于奖金,这里是切换方法:

- (void)toggleImageViewOn:(UIImageView *)theImageView {
    [theImageView setImage:[UIImage imageNamed:@"on.png"]];
}

- (void)toggleImageViewOff:(UIImageView *)theImageView {
    [theImageView setImage:[UIImage imageNamed:@"off.png"]];
}

6 个答案:

答案 0 :(得分:2)

您是否围绕此for循环设置了动画上下文(UIView类方法可以做到这一点)?没有它,立即改变而不是动画。

答案 1 :(得分:1)

问题是你没有给任何UIImages时间画画。绘图代码经过优化,只能绘制所需的内容 - 渲染所有中间阶段都得到了优化。

睡觉主线程实际上没有机会运行。

比尔是正确的,你需要围绕循环设置一个动画上下文。这将捕获您所做的所有UIView更改,然后将其播放出来。最简单的方法是使用Core Animation。核心动画'记录'UIElemenets中的变化并播放它们。您的代码(没有睡眠)在Core Animation块中可以正常工作。

Apple有一个合理的核心动画食谱on their site

答案 2 :(得分:0)

嘿帕特里克。看看UIImageView的animationImages属性,以及animationRepeatCount和animationDuration属性。如果将开/关图像放入数组并将其指定为animationImages属性,则应该能够控制重复和持续时间以获得所需的效果。

希望有所帮助!

答案 3 :(得分:0)

谢谢你。我已经查看了UIIMageView的animationImages属性。这不正是我试图做的事情。我在几个彼此靠近的UIImageView之间骑行,给人的印象是灯光在它们之间移动并在它们之间骑行。所以单个UIImageView的动画是彼此分开的,因为我需要在代码中根据需要交换图像。

答案 4 :(得分:0)

您将循环移动到后台线程是正确的,但您还需要确保为主运行循环提供更新UI的机会。您应该可以使用类似

的替换直接调用toggleImageViewOn:和toggleImageViewOff:
[self performSelectorOnMainThread:@selector(toggleImageViewOn:) withObject:[Images objectAtIndex:i] waitUntilDone:NO];

这将在主线程上进行UI更新,并且不等到更新完成后,您将为主运行循环提供一个到达终点的机会。你遇到了与进度条相同的问题,在循环结束之前它们不会改变,除非你从具有上述UI更新调用的后台线程进行更新。

答案 5 :(得分:0)

调用peformSelectorOnMainThread:withObject:waitUntilDone:从后台线程的循环确实更快地更新视图,我认为我将需要。我很好奇为什么我需要在主线程上进行UIImageView交换?为什么不在后台线程上更改它然后使用NSThread的sleepForTimeInterval允许主线程还是更新绘图?

我想我需要阅读运行循环以及绘图更新的位置。

非常感谢你的帮助。 (我还要尝试一下Bill Dudney的一些额外建议,我认为这些建议将基于CoreAnimation)