【发布时间】:2014-02-19 15:06:50
【问题描述】:
几天前我想在晚上写一些愚蠢的东西,我想我会在模拟器上观看元素动画来放松一下。但事实证明,这两天让我很头疼。
背景:
我想我会在 320 X 480 的屏幕上的每个像素上随机绘制一个字母。
我将有一个包含 26 个字母的数组,并使用 arc4Random % 26 来提取一个随机字母。
首先我使用了UIGraphicsBeginImageInContextWithOptions 并将图像添加到图像视图中,该视图被添加为我的视图的子视图。
完全没问题。
但后来我意识到,为什么要等呢?让我们做一个 2 for 循环(外部:480 -> 内部:320)
一旦第一个内部循环完成,将该数组发送到 dispatch_async 并让它在 drawRect 中绘制,然后当下一次迭代完成时,将其发送到另一个 dispatch_async 等等,直到两个循环都完成。
我的痛苦由此开始/-之后......
原因:
for 循环太紧太快。因此,在我发送包含 320 个元素的数组后,我最终将 2 个 for 循环包装在 dispatch_async 中,并在内部 for 循环中放置了 sleep(1);。
但后来我意识到:通过使用sleep(1),它超越了想要更快绘图的目的。事实上,这比根本不使用GCD 需要更长的时间。超过 25 秒。
所以,我继续尝试使用semaphore,并在将dispatch_async 中的数组发送到drawRect 之前只有3200 个可用插槽时创建一个;
问题:
比赛条件。我会得到意外的数组越界错误。错误不一致;有时它发生得更晚,有时更早。我认为这与未正确使用 CGD 有关。
所以我的问题是:
我凭直觉知道这可以通过GCD 进行微调和解决。但我就是不知道怎么做。我无计可施。
我真正想要的是能够更新屏幕的绘图,而不是等待整个东西被绘制出来。要么在屏幕上逐点显示一个点,要么一个接一个地显示,而不必调用setNeedsDisplay,但最好改为调用setNeedsDisplayinRect。
我想我会剖析绘图元素的各个部分,并将每个部分发送到它自己的 dispatch_async,每个部分只负责绘制它的部分,并且由于同时运行,它会在屏幕上非常快速地渲染绘图。
但是,我又一次没有想法,最终充满挫败感。
for(int y = 0; y < 480; y++)
{
for(int x = 0; x < 320; x++)
{
//get a random letter here and insert it into the array (myArray)
}
dispatch_async(myQueue, ^
{
dispatch_async(dispatch_async_get_main_queue(),^
{
[self.myView processRowDrawing:myArray];
}
}
[myArray removeAllObjects];
//as mentioned: I tried to put a sleep() here because the loop is faster the the drawing
}
- (void)processRowDrawing:(NSMutableArray*)array
{
for(x = 0; x < array.count; x++)
{
//cell here `setNeedsDisplayInRect:` to draw a row
}
}
至于信号量的版本,我只是简单的在create和signal中设置了一个大数来调用[self.myView processRowDrawing:myArray];,但是由于绘图比for循环慢,所以没有用。
是否有可能用GCD 以一种漂亮而优雅的方式解决这个问题,方法是同时分割绘图部分并将其发送到drawRect 并让这些部分一点一点地显示在屏幕上,而不是等待它整个?
逐行或逐格并看到它们被绘制?同样,我想在这里使用GCD。
为此失眠了。请指教。
附:我已经尝试过使用CADisplayLink。
【问题讨论】: