【问题标题】:Core Animation Warning: "uncommitted CATransaction"核心动画警告:“未提交的 CATransaction”
【发布时间】:2013-01-02 10:41:47
【问题描述】:

我收到以下仅使用设备的警告:

CoreAnimation: warning, deleted thread with uncommitted CATransaction; created by:
0   QuartzCore                          0x3763c65d <redacted> + 220
1   QuartzCore                          0x3763c541 <redacted> + 224
2   QuartzCore                          0x3763fe2f <redacted> + 30
3   QuartzCore                          0x3763b9bf <redacted> + 318
4   QuartzCore                          0x3763b87b <redacted> + 50
5   QuartzCore                          0x3763b80b <redacted> + 538
6   MyApp                              0x000df597 -[CommonClass orangeGradient:] + 382
7   MyApp                              0x000f70e1 -[HomeViewController updateStatusBar] + 1700
8   MyApp                              0x000f61bd -[HomeViewController statusRecieved] + 224
9   MyApp                              0x000cd323 -[CommonClass statusReceivedFromServer] + 142
10  MyApp                              0x000d833d -[CommonClass accountStatus] + 7416
11  Foundation                          0x35a3767d <redacted> + 972
12  libsystem_c.dylib                   0x35c9a311 <redacted> + 308
13  libsystem_c.dylib                   0x35c9a1d8 thread_start + 8

我在栈顶的方法如下:

- (void)orangeGradient: (UILabel *)fillLabel {
@synchronized([CommonClass class]) {
CAGradientLayer * gradientLayer = [CAGradientLayer layer];
gradientLayer.frame = fillLabel.bounds;
gradientLayer.colors = [NSArray arrayWithObjects:(id)[UIColorFromRGB(0xfbb250) CGColor],(id)[UIColorFromRGB(0xf47c2a) CGColor], nil];
[fillLabel.layer addSublayer:gradientLayer];
}
}

知道为什么会出现这种情况,以及如何解决这个问题吗?

【问题讨论】:

  • 你是在UIVIewAnimation还是NSOperation下调用orangeGradient?
  • 直接从其他类调用方法...是NSOperation吗?
  • 如果你在线程上使用 performSelector 那么它就是 NSOperation。基本上这个问题发生在 NSOperation 在 CoreAnimation 执行完成之前完成。这两个类之间一定存在某种关系,您需要弄清楚代码中的某个地方。

标签: iphone ios core-animation quartz-core catransaction


【解决方案1】:

看起来orangeGradient: 是从后台线程调用的。 Core Animation 将所有更改分组到 CATransactions 中。通常这是在运行循环中自动完成的。在后台线程上(通常)没有运行循环,因此您必须自己创建事务:

- (void)orangeGradient: (UILabel *)fillLabel {
    @synchronized([CommonClass class]) {
        [CATransaction begin];
        CAGradientLayer * gradientLayer = [CAGradientLayer layer];
        gradientLayer.frame = fillLabel.bounds;
        gradientLayer.colors = [NSArray arrayWithObjects:(id)[UIColorFromRGB(0xfbb250) CGColor],(id)[UIColorFromRGB(0xf47c2a) CGColor], nil];
        [fillLabel.layer addSublayer:gradientLayer];
        [CATransaction commit];
    }
}

还有另一个问题:UIKit 不是线程安全的。您不能在后台线程上的 UILabel 上调用 bounds

【讨论】:

  • 或者我应该使用performSelectorInMainThread: 调用这个方法吗?
  • @NikitaP 是的,如果你使用 UILabel,你无论如何都会绑定到主线程。所以你也可以摆脱@synchronized
  • @NikolaiRuhe 这是有道理的。为此+1,但她已经在主线程中调用了这个函数,所以从后台线程更新标签不是问题,但我想明确放置 CATTransaction 应该可以解决这个问题。
【解决方案2】:

检查代码中是否有未提交 CATransaction。您将需要按照以下方式执行此操作;

[CATransaction begin];
[CATransaction setDisableActions:YES];
[commonClassObject orangeGradient:lblFill];
[CATransaction commit];

[编辑]

基本上,当 NSOperation 在 CoreAnimation 执行完成之前完成时,就会发生此问题。这两个类之间一定存在某种关系,您需要在代码中的某个地方弄清楚这一点。

【讨论】:

  • 警告信息清楚地表明问题是未提交的 CATransaction。请从您调用此方法的位置发布您的代码。
  • 这只是一个类似的调用: UILabel *lblFill = [[UILabel alloc]initWithFrame:CGRectMake (0,0,100,30)]; [commonClassObject orangeGradient:lblFill];
【解决方案3】:

我只是补充一点,我在后台线程中遇到了与 initWithFrame 相同的问题。

似乎从iOS 7及以上开始,对UIKit的一些调用必须在主线程下进行,不能从后台线程调用。

另请注意,在多次发出此类警告后,我的应用完全停止响应。所以最好不要忽视这样的警告。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-02
    • 2013-10-28
    • 1970-01-01
    • 2011-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多