Selon les documents, Malheureusement, la taille renvoyée par cette fonction n'est jamais exacte. Voici ce que je fais: p> La taille renvoyée a toujours la largeur correcte calculée, mais la hauteur est toujours légèrement plus courte que ce qui est attendu. P> Est-ce le moyen correct d'utiliser cette méthode? P> y a-t-il d'autre moyen de mettre en place un texte de base? P> semble que je ne suis pas le seul à rencontrer des problèmes avec cette méthode. Voir https://devforums.apple.com/message/181450 . P> Modifier:
J'ai mesuré la même chaîne avec quartz à l'aide de Texte principal: 133.569336 x 16.592285 P>
Quartz: 135.000000 x 31.000000 P>
blockQuote> p> CTFRASESETTERSUGGERFRESIMESWITHCONSTRESSIONS () CODE> "Détermine la taille du cadre nécessaire à une plage de cordes".
Taillewithfont: code>, fournissant la même police à la chaîne attribuée et à quartz. Voici les mesures que j'ai reçues: P>
6 Réponses :
Pour une seule image de ligne, essayez ceci:
CGFloat wrongHeight = ascent-descent; CGSize textSize = CGSizeMake(width, wrongHeight);
Merci beaucoup, MO. Cela m'a aidé à trouver ce qui semble être une solution de contournement fiable pour le suggérant des étiquettes multilignes.
Heureux d'avoir pu aider. Avez-vous vérifié si j'avais raison sur le wrongheight code>? Je veux déposer un rapport de bogue. Ps. merci gf.
Essayez ceci .. semble fonctionner:
+(CGFloat)heightForAttributedString:(NSAttributedString *)attrString forWidth:(CGFloat)inWidth { CGFloat H = 0; // Create the framesetter with the attributed string. CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString( (CFMutableAttributedStringRef) attrString); CGRect box = CGRectMake(0,0, inWidth, CGFLOAT_MAX); CFIndex startIndex = 0; CGMutablePathRef path = CGPathCreateMutable(); CGPathAddRect(path, NULL, box); // Create a frame for this column and draw it. CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(startIndex, 0), path, NULL); // Start the next frame at the first character not visible in this frame. //CFRange frameRange = CTFrameGetVisibleStringRange(frame); //startIndex += frameRange.length; CFArrayRef lineArray = CTFrameGetLines(frame); CFIndex j = 0, lineCount = CFArrayGetCount(lineArray); CGFloat h, ascent, descent, leading; for (j=0; j < lineCount; j++) { CTLineRef currentLine = (CTLineRef)CFArrayGetValueAtIndex(lineArray, j); CTLineGetTypographicBounds(currentLine, &ascent, &descent, &leading); h = ascent + descent + leading; NSLog(@"%f", h); H+=h; } CFRelease(frame); CFRelease(path); CFRelease(framesetter); return H; }
Cela semble être la seule solution fiable que je puisse imaginer. Toutes les autres manières échouent pour certains cas.
Si vous utilisez zéro comme hauteur, il ne limite pas la hauteur à une hauteur. J'ai écrit une catégorie pour cette question qui fonctionne pour moi dans tous les cas. Voir Stackoverflow.com/Questtions/16586190/...
Si quelqu'un est intéressé, cela a essentiellement la même performance que ctfriesettersuggestfresizewithconstraints code> sauf qu'il est en fait correct à chaque fois
Cela peut sembler étrange mais j'ai trouvé que si vous utilisez la fonction CEIL code>, puis ajoutez +1 à la hauteur, elle fonctionnera toujours. De nombreuses API tiers utilisent cette astuce. P>
Le problème est que vous devez appliquer un style de paragraphe au texte avant de le mesurer. Si vous ne le faites pas, vous obtenez la valeur par défaut de 0,0. J'ai fourni un échantillon de code pour comment faire cela dans ma réponse à un duplicata de cette question ici ici https://stackoverflow.com/a/ 10019378/1313863 . P>
Ressuscation. P>
Lors de la détermination initiale où des lignes doivent être placées dans une trame, le texte de base semble masser la descente + la descente aux fins du calcul de la ligne d'origine. En particulier, il semble que 0,2 * (ascension + descente) soit ajouté à l'ascension, puis la descente et l'ascension résultante sont modifiés par J'ai déjà démissionné pour simplement envisager une ligne de démarrer à sa base et ne pas essayer de comprendre ce que les lignes réelles atterrissent. Malheureusement, cela ne semble toujours pas être suffisant: les styles de paragraphe ne sont pas reflétés dans Il semble Et même alors il ne prend toujours pas de styles de paragraphe en considération>: | p>
Aucune des options ne nous est pertinente: elles réduisent les limites record en prenant en compte certains choix de conception de polices (ou augmentent les limites recouvertes de manière aléatoire, dans le cas du nouveau plancher (x + 0,5) code>, puis les positions de base sont calculé sur la base de ces ascensions et descentes ajustées. Ces deux étapes sont affectées par certaines conditions dont je ne suis pas sûr, et j'ai aussi déjà oublié les styles de paragraphe de points, malgré cela que je ne sais que quelques jours il y a quelques jours. P>
CTLINEGETTYPOGROCOGOGOGOGULAIS () CODE>, et certaines polices comme Klee qui ont des mentionnements non nuléreuses en train de traverser le chemin rect! Je ne sais pas quoi faire à propos de cela ... probablement pour une autre question. P>
ctlinegetboundswithoptions (ligne, 0) code> obtient les limites de la ligne appropriées, mais pas tout à fait: il y a une lacune entre les lignes et avec certaines polices (Klee à nouveau) l'écart est négatif et le Les lignes se chevauchent ... Je ne sais pas quoi faire à ce sujet. : | Au moins nous sommes légèrement plus proches ?? p>
CTLINEGETBOUDSWITHOPTIONS () CODE> n'est pas répertorié sur le site de la documentation d'Apple, éventuellement due à un bogue dans la version actuelle de leur générateur de documentation. Il s'agit d'une API entièrement documentée, cependant, vous le trouverez dans les fichiers d'en-tête et il a été longuement discuté à la Session 226 de la WWDC 2012. P>
kctlineboundsincluSeextents code>). Une option utile en général, cependant, est
kctlineboundsuseglyphpathbounds code>, ce qui est équivalent à
ctlinegetimagebounds () code> mais sans avoir besoin de spécifier un
CGContext code> (et donc sans être soumis à une matrice de texte existante ou à la CTM). P>
Réponse de Ing.Conti mais à Swift 4: J'ai essayé de le garder comme 1: 1 avec le code de l'objectif C mais Swift n'est pas aussi agréable lors de la manipulation des pointeurs de manipulation de certains changements étaient nécessaires pour le casting. p> J'ai également fait des points de repère comparant ce code (et son homologue Objc) à une autre méthode de hauteur. En tant qu'entrée, j'ai utilisé une chaîne attribuée énorme et très complexe comme entrée et l'a également fait sur la carte SIM afin que les temps eux-mêmes ne soient pas de sens, mais les vitesses relatives sont correctes. P> Runtime for 1000 iterations (ms) BoundsForRect: 8909.763097763062
Runtime for 1000 iterations (ms) layoutManager: 7727.7010679244995
Runtime for 1000 iterations (ms) CTFramesetterSuggestFrameSizeWithConstraints: 1968.9229726791382
Runtime for 1000 iterations (ms) CTFramesetterCreateFrame ObjC: 1941.6030206680298
Runtime for 1000 iterations (ms) CTFramesetterCreateFrame-Swift: 1912.694974899292
eu même problème. Calcule toujours une ligne de moins que si je le demande pour calculer 3 lignes, cela me donnera le calcul correct pour 2 .. etc.
Voir cette question connexe: