核心动画警告:“未提交的 CATransaction”
Posted
技术标签:
【中文标题】核心动画警告:“未提交的 CATransaction”【英文标题】:Core Animation Warning: "uncommitted 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 执行完成之前完成。这两个类之间一定存在某种关系,您需要弄清楚代码中的某个地方。 【参考方案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的一些调用必须在主线程下进行,不能从后台线程调用。
另请注意,在多次发出此类警告后,我的应用完全停止响应。所以最好不要忽视这样的警告。
【讨论】:
以上是关于核心动画警告:“未提交的 CATransaction”的主要内容,如果未能解决你的问题,请参考以下文章