从后台线程更改CALayer的属性是否安全?

时间:2012-06-01 21:58:17

标签: ios multithreading calayer

我想做一个响应设备动作的动画,即使UI线程暂时忙,我也希望它保持平滑。动画包括更改CALayer的贝塞尔曲线路径。我试过从辅助线程做到这一点,但我偶尔会挂起主线程有一个已删除的堆栈。我在做什么完全没有希望?这是我在线程中所做的:

[CATransaction lock];
[CATransaction setValue:(id)kCFBooleanTrue
                 forKey:kCATransactionDisableActions];
[CATransaction begin];
myLayer.path = [UIBezierPath bezierPathWithOvalInRect:theRect].CGPath;
myLayer.bounds = theBounds;
[CATransaction commit];

[CATransaction flush];
[CATransaction setValue:(id)kCFBooleanFalse
                 forKey:kCATransactionDisableActions];
[CATransaction unlock];

2 个答案:

答案 0 :(得分:4)

这是我的版本。

dispatch_async(dispatch_get_main_queue(), ^{
            myLayer.path = [UIBezierPath bezierPathWithOvalInRect:theRect].CGPath;
            myLayer.bounds = theBounds;
        });

Dispatch队列为您提供了从本地范围提取变量的优势,而无需担心实现中间数据结构。

答案 1 :(得分:2)

禁止从除uithread之外的任何线程更新ui 所以你必须做以下事情:

- (void) updateUI
{
[CATransaction lock];
[CATransaction setValue:(id)kCFBooleanTrue
                 forKey:kCATransactionDisableActions];
[CATransaction begin];
myLayer.path = [UIBezierPath bezierPathWithOvalInRect:theRect].CGPath;
myLayer.bounds = theBounds;
[CATransaction commit];

[CATransaction flush];
[CATransaction setValue:(id)kCFBooleanFalse
                 forKey:kCATransactionDisableActions];
[CATransaction unlock];
}

和其他帖子

[self performSelectorOnMainThread:@selector(updateUI) withObject:nil waitUntilDone:YES];