CoreText在多个线程中运行时崩溃

时间:2011-04-12 23:17:18

标签: iphone cocoa-touch ios core-text

我的核心文本有一个非常奇怪的问题,有时会随机地,有时可重复地崩溃我的应用程序。我用它来布局并渲染几页。我在后台异步执行此操作以阻止用户界面。

虽然这一般工作正常,但有时会崩溃。所有这些崩溃都发生在同一条线上:

framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)myText);

事实上,他们似乎也来自框架中的类似点。我知道你不喜欢它,但这里是崩溃日志的负责人:

Thread 8 Crashed:
0   ???                             0x0764f446 typeinfo for FT::data_stream + 6
1   libCGFreetype.A.dylib           0x076048b8 FT::font::copy_table(unsigned int) const + 94
2   libCGFreetype.A.dylib           0x0760b085 (anonymous namespace)::copy_table(void*, unsigned int) + 53
3   CoreText                        0x00f9592e TBaseFont::CopyTable(unsigned int) const + 334
4   CoreText                        0x00f670f6 TAATMorphTable::TAATMorphTable(TLine&, long, unsigned int) + 110
5   CoreText                        0x00f6744c TAATMorphTableMorx::TAATMorphTableMorx(TLine&, long, TGlyphList<TDeletedGlyphIndex>&) + 54
6   CoreText                        0x00f53eb5 TShapingEngine::ShapeGlyphs(TLine&, TCharStream const&, CFRange&, TGlyphList<TDeletedGlyphIndex>*) + 215
7   CoreText                        0x00f579ce TTypesetter::FinishEncoding(TLine&, signed char, TGlyphList<TDeletedGlyphIndex>*) const + 260
8   CoreText                        0x00f6664b TTypesetterAttrString::Initialize(__CFAttributedString const*) + 543
9   CoreText                        0x00f6683e TTypesetterAttrString::TTypesetterAttrString(__CFAttributedString const*) + 158
10  CoreText                        0x00f6102e TFramesetterAttrString::TFramesetterAttrString(__CFAttributedString const*) + 86
11  CoreText                        0x00f6099e CTFramesetterCreateWithAttributedString + 78
...

我记得的所有崩溃都在FT::font::copy_table函数中。有趣的是,字体要求越复杂,崩溃的频率就越高。中文文本几乎总是崩溃 - 这些字体看起来很复杂。

解决方法:我找到的解决方法是在主队列或单独的队列中将调用序列化为CTFramesetterCreateWithAttributedString。问题是这个单一调用占总布局的79%并渲染运行时间。所以我很乐意将它放在多个线程中。

问题:围绕这一点的任何专业人士可以提供帮助吗? 对我来说这听起来像是一个内心深处的竞争条件。我没有发现任何声明CoreText可能没有使用线程的东西。我明天会提交一个bug。但是,我可能也错过了一些东西。有什么建议吗?

谢谢, 最大

5 个答案:

答案 0 :(得分:7)

我在WWDC期间询问了一些工程师他们是否知道这个问题。答案:是的。事实上,类型子系统中存在一些问题。他们可能有一天会做一个修复,但是现在剩下要做的就是对所有文本布局进行顺序化。 :(

每个人:请提起文件错误!

答案 1 :(得分:4)

以下是documentation所说的内容:

  

多核注意事项:全部   核心文本中的各个函数是   线程安全。字体对象(CTFont,   CTFontDescriptor,并关联   对象)可以同时使用   通过多个操作,工作队列,   或线程。但是,布局   对象(CTTypesetter,CTFramesetter,   CTRun,CTLine,CTFrame和相关联   对象)应该在一个单独使用   操作,工作队列或线程。

所以我猜无法将序列化调用CTFramesetterCreateWithAttributedString

答案 2 :(得分:1)

第一次使用时,CoreText需要一段时间来初始化字体查找表。我想你可以通过在转到多个线程之前首先触发此表的加载来摆脱你的问题。

请参阅http://www.cocoanetics.com/2011/04/coretext-loading-performance/了解方法。

答案 3 :(得分:0)

请确保在重新打开之前保留框架。这是真的并不意味着在4.0之前使用异步!

CFRelease(framesetter);

你能提供Xcode版本吗?你正在使用iOS吗?

答案 4 :(得分:0)

修复我:-)不再崩溃

旧代码

NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:aText];
[attributedString addAttribute:(id)kCTFontAttributeName value:(id)aFontRef range:NSMakeRange(0, [aText length])];

CTFramesetterRef framesetterRef = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attributedString);

新代码

CFMutableAttributedStringRef attributedStringRef = CFAttributedStringCreateMutable(nil, 0);
CFAttributedStringBeginEditing(attributedStringRef);
CFAttributedStringReplaceString(attributedStringRef, CFRangeMake(0, 0), (CFStringRef)aText);
CFAttributedStringSetAttribute(attributedStringRef, CFRangeMake(0, aText.length), kCTFontAttributeName, aFontRef);
CFAttributedStringEndEditing(attributedStringRef);

CTFramesetterRef framesetterRef = CTFramesetterCreateWithAttributedString(attributedStringRef);