1

使用后台线程更新 UI 的理想方式是

dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
    //Background Thread
    dispatch_async(dispatch_get_main_queue(), ^(void){
        //Run UI Updates
    });
});

但是即使不使用主队列,我们​​也可以更新 UI

dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
    //Background Thread
    //Run UI Updates
});

所以我使用 beizer 路径来绘制一些点,这些点来自 iPad UIPanGestureRecognizer。现在我在主线程上绘制这些点并旋转这些点以获得新点并使用后台线程(并发)绘制这些新点。这是我的代码:

CGPoint touchPoint = [sender locationInView:self.view];
[pencilLayer[0] addPoint:touchPoint];
for(int i = 1; i < 4; i++)
{
    dispatch_async(privateQueue, ^{
        CGPoint point = Rotatepoint(500, 500, 45(degree), touchPoint);
        [pencilLayer[i] addPoint:point];
    });
}

我的问题是:主线程和私有队列应该同时在 UI 上绘制。为什么释放手势后,privateQueue 在 UI 上绘制点?

4

2 回答 2

2

好吧,根据文档,通常最好将操作 UI 的代码保留在主线程上:

线程和您的用户界面

如果您的应用程序具有图形用户界面,建议您接收与用户相关的事件并从应用程序的主线程启动界面更新。这种方法有助于避免与处理用户事件和绘制窗口内容相关的同步问题。一些框架,例如 Cocoa,通常需要这种行为,但即使对于那些不需要这种行为的框架,将这种行为保留在主线程上具有简化管理用户界面的逻辑的优势。

现在,在您的特定情况下,这可能正是您发生的事情的原因。但无论如何,在您的特定情况下,我认为没有充分的理由在私人队列上执行绘图。但是你应该把它放在主线程上是有原因的——代码操作 UI,所以建议把它放在主线程上(见上面的参考资料)。此外,点画不是性能详尽的操作 - 没有充分的理由将其放在背景上。

所以我建议删除私有队列上的调度并简单地使用这个:

CGPoint touchPoint = [sender locationInView:self.view];
[pencilLayer[0] addPoint:touchPoint];
for(int i = 1; i < 4; i++)
{
    CGPoint point = Rotatepoint(500, 500, 45(degree), touchPoint);
    [pencilLayer[i] addPoint:point];
}

此外,请查看有关线程和 UI 的博客条目。

于 2018-02-01T11:01:50.630 回答
0

您为后台队列中的每个点添加一个项目。这应该不是很高效,并且可能会导致滞后。最好将单个项目添加到后台队列:

CGPoint touchPoint = [sender locationInView:self.view];

dispatch_async(privateQueue, ^{
    [pencilLayer[0] addPoint:touchPoint];
    for(int i = 1; i < 4; i++)
    {
            CGPoint point = Rotatepoint(500, 500, 45(degree), touchPoint);
            [pencilLayer[i] addPoint:point];
    }
});

这将一次绘制所有点。

于 2018-02-01T11:20:36.180 回答