Question CoreText se bloque lorsqu'il est exécuté dans plusieurs threads


J'ai un problème très étrange avec le texte de base, qui bloque parfois mon application de manière aléatoire et parfois reproductible. Je l'utilise pour disposer et rendre quelques pages. Je le fais de manière asynchrone en arrière-plan pour ne pas bloquer l'interface utilisateur.

Bien que cela fonctionne bien en général, il parfois des accidents. Tous ces accidents se produisent sur la même ligne:

framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)myText);

En fait, ils semblent également provenir d'un point similaire dans le cadre. Je sais que vous ne l'aimez pas, mais voici la tête d'un journal de bord:

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
...

Tous les accidents dont je me souviens ont été dans le FT::font::copy_table fonction. Fait intéressant, plus les exigences en matière de polices sont compliquées, plus les accidents sont fréquents. Le texte chinois s'écroule presque toujours - ces polices semblent être assez compliquées.

Solution de contournement: La solution de contournement que j'ai trouvée consiste à séquencer les appels à CTFramesetterCreateWithAttributedString dans la file d'attente principale ou une autre. Le problème est que cet appel unique représente 79% de la mise en page totale et le temps d'exécution du rendu. J'aimerais donc l'avoir dans plusieurs threads.

Question: Des pros autour de vous pourraient aider? Pour moi, cela ressemble à une situation de course quelque part au fond. Je n'ai rien trouvé indiquant que CoreText ne puisse pas être utilisé en thread. Et je déposerai un bug demain. Cependant, je pourrais aussi avoir manqué quelque chose. Aucun conseil?

Merci, Max


13
2018-04-12 23:17


origine


Réponses:


J'ai demandé à certains des ingénieurs de la WWDC s'ils connaissaient le problème. La réponse: OUI. Et il y a en fait des problèmes dans le sous-système de type. Il se peut qu’ils fassent un jour un correctif, mais pour l’instant, il ne reste plus qu’à séquencer tout le texte. :(

Toutes les personnes: S'IL VOUS PLAÎT FICHIER BOGUES!


7
2018-06-17 13:30



Voici ce que le Documentation dit:

Considérations sur le multicœur: Tous   les fonctions individuelles dans Core Text sont   fil de sécurité. Objets de police (CTFont,   CTFontDescriptor, et associé   objets) peuvent être utilisés simultanément   par des opérations multiples, des files d'attente de travail,   ou des fils. Cependant, la mise en page   objets (CTTypesetter, CTFramesetter,   CTRun, CTLine, CTFrame et associés   objets) doivent être utilisés dans un seul   opération, file d'attente de travail ou thread.

Donc, je suppose qu'il n'y a pas moyen de sérialiser les appels à CTFramesetterCreateWithAttributedString.


4
2018-05-13 18:18



CoreText met du temps à initialiser la table de recherche des polices lorsque vous l'utilisez pour la première fois. J'imagine que vous pourriez être en mesure de vous débarrasser de votre problème en déclenchant d'abord un chargement de cette table avant de passer à plusieurs threads.

Voir http://www.cocoanetics.com/2011/04/coretext-loading-performance/ pour une méthode comment.


1
2018-06-19 03:07



Assurez-vous de conserver le cadre avant de le rouvrir. C'est VRAIMENT pas destiné à être utilisé asynchrone avant 4.0!

CFRelease(framesetter);

Pouvez-vous également fournir la version de Xcode & iOS avec laquelle vous travaillez?


0
2018-04-21 12:50



réparer de moi :-) plus de crash

ancien code

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

CTFramesetterRef framesetterRef = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attributedString);

nouveau code

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); 

0
2017-08-29 17:22