Crénage dans iOS UITextView

Pour ce qui est apparemment un 'bug', UITextView ne semble pas prendre en charge le crénage comme les autres éléments UIKit. Y a-t-il une solution de contournement pour que le crénage fonctionne?

Pour être clair, je parle de l'espacement entre les paires de caractères qui sont définies dans le file de police, pas de l'espacement général entre tous les caractères. L'utilisation d'un NSAtsortingbutedSsortingng avec NSKernAtsortingbuteName ajustera l'espacement entre tous les caractères, mais les paires de caractères embeddedes ne fonctionnent toujours pas.

Par exemple:

entrez la description de l'image ici

Y at-il une solution de contournement pour résoudre ce problème?

Une solution de contournement simple que j'ai découverte consiste à append des styles css à l'UITextView qui activer le crénage. Si j'utilise la méthode non documentée setContentToHTMLSsortingng: je peux injecter le CSS à la vue web secrète dans la vue de text.

 NSSsortingng *css = @"*{text-rendering: optimizeLegibility;}"; NSSsortingng *html = [NSSsortingng ssortingngWithFormat:@"<html><head><style>%@</style></head><body>Your HTML Text</body></html>", css]; [textView performSelector:@selector(setContentToHTMLSsortingng:) withObject:html]; 

Cela résout le problème immédiatement; Cependant, il semble très probable que l'application sera rejetée. Y a-t-il un moyen sûr de faire glisser quelques CSS dans la vue du text?

D'autres solutions de contournement que j'ai expérimentées incluent:

Utilisation d'une vue Web et de la propriété contenteditable. Ce n'est pas l'idéal car WebView fait un tas de choses supplémentaires qui gênent, par exemple la vue des accessoires de saisie qui ne peut pas être facilement cachée.

Sous- UITextView un UITextView et rendu du text manuellement avec le text principal. C'est plus complexe que ce que j'avais espéré car toutes les sélections doivent être reconfigurées. En raison des sous-classs privées UITextPosition de UITextPosition et UITextRange c'est une énorme douleur dans le cul si ce n'est pas complètement impossible.

Vous avez raison de dire que votre application sera probablement rejetée en utilisant @selector(setContentToHTMLSsortingng:) . Vous pouvez cependant utiliser une astuce simple pour build dynamicment le sélecteur afin qu'il ne soit pas détecté lors de la validation.

 NSSsortingng *css = @"*{text-rendering: optimizeLegibility;}"; NSSsortingng *html = [NSSsortingng ssortingngWithFormat:@"<html><head><style>%@</style></head><body>Your HTML Text</body></html>", css]; @try { SEL setContentToHTMLSsortingng = NSSelectorFromSsortingng([@[@"set", @"Content", @"To", @"HTML", @"Ssortingng", @":"] componentsJoinedBySsortingng:@""]); #pragma clang diagnostic push #pragma clang diagnostic ignored "-Warc-performSelector-leaks" [textView performSelector:setContentToHTMLSsortingng withObject:html]; #pragma clang diagnostic pop } @catch (NSException *exception) { // html+css could not be applied to text view, so no kerning } 

En enveloppant l'appel dans un bloc @ try / @ catch, vous vous assurez également que votre application ne plantera pas si la méthode setContentToHTMLSsortingng: est supprimée dans une future version d'iOS.

L'utilisation d'API privées n'est généralement pas recommandée, mais dans ce cas, je pense qu'il est tout à fait logique d'utiliser un petit hack vs réécrire UITextView avec CoreText.

Essaye ça:

 [textView_ setValue:@"hello, <b>world</b>" forKey:@"contentToHTMLSsortingng"]; 

Cela fonctionne dans mon test. Je ne l'ai pas essayé dans l'App Store bien sûr.

Après quelques searchs, j'ai trouvé que la raison de l'absence de Kerning est que UITextView utilise en interne un UIWebDocumentView dont Kerning est désactivé par défaut.

Quelques infos sur les rouages ​​de UITextView: http://www.cocoanetics.com/2012/12/uitextview-caught-with-trousers-down/

Malheureusement, il n'y a pas de méthode approuvée pour activer Kerning, je déconseillerais certainement d'utiliser un hack utilisant un sélecteur camouflé.

Voici mon radar, je vous suggère de le duper: http://www.cocoanetics.com/2012/12/radar-uitextview-ignores-font-kerning/

Dans ce cas, je soutiens que lorsque nous définissons le text sur UITextView via setAtsortingbutedText, les développeurs s'attendent à ce que Kerning soit activé par défaut, car c'est de cette manière que le text serait le plus proche du rendu du text via CoreText.

Avez-vous regardé ici: https://github.com/AliSoftware/OHAtsortingbutedLabel ? En regardant ce projet, il apparaît qu'il y a plusieurs applications dans le magasin d'applications qui utilisent le balisage (fourni par cette class). Peut-être pourriez-vous utiliser cette class ou en tirer quelques idées de mise en œuvre. Peut-être que votre application en tant que telle sera acceptée.

Avec iOS6, UITextView a un nouvel atsortingbut atsortingbutedText , auquel vous pouvez affecter un NSAtsortingbutedSsortingng . Je n'ai pas essayé, mais il serait intéressant de voir si vous obtenez le crénage que vous searchz si vous définissez cet atsortingbut de votre affichage de text plutôt que l'atsortingbut de text . Et il a l'avantage d'être une interface publique.

Il n'y a pas besoin de recourir à des methods privées. Vous pouvez facilement truquer en modifiant dynamicment la propriété atsortingbutedText du champ de text chaque fois que le text change en vous abonnant à la notification UITextFieldTextDidChangeNotification :

 - (void)viewDidLoad { // your regular stuff goes here [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textDidChangeNotification:) name:UITextFieldTextDidChangeNotification object:nil]; } - (void)textDidChangeNotification:(NSNotification *)notification { // you can of course specify other atsortingbutes here, such as font and text color CGFloat kerning = -3.; // change accordingly to your desired value NSDictionary *atsortingbutes = @{ NSKernAtsortingbuteName: @(kerning), }; UITextField *textField = [notification object]; textField.atsortingbutedText = [[NSAtsortingbutedSsortingng alloc] initWithSsortingng:textField.text atsortingbutes:atsortingbutes]; }