Kerning in iOS7/8 UITextView when using an NSAttributedString built from HTML

502 views Asked by At

I am having trouble getting kerning to work inside a UITextView on iOS 7 and 8. The kerning works fine when I set the string directly, or when I use an NSAttributedString that I construct manually, but simply doesn't work when I generate the NSAttributedString from HTML.

The following code will kern the text correctly:

self.textView.attributedText = [[NSAttributedString alloc] initWithString:@"Test"];

But the following does not:

NSString *html = @"<html><head><style>\
                  body { font-size: 40px; text-rendering: optimizeLegibility; }\
                  </style></head>\
                  <body>Test</body></html>";
NSAttributedString *attrString = [[NSAttributedString alloc]
              initWithData:[html dataUsingEncoding:NSUTF8StringEncoding]
              options:@{
                  NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
                  NSCharacterEncodingDocumentAttribute: @(NSUTF8StringEncoding)
              }
              documentAttributes:nil error:nil];
self.textView.attributedText = attrString;

What am I doing wrong?

1

There are 1 answers

0
Nick Street On

When generating an NSAttributedString and the NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType option is set, iOS adds an NSKern = 0 attribute to the attributed string. You can inspect this by simply logging the attributed string:

Test{
    NSColor = "UIDeviceRGBColorSpace 0 0 0 1";
    NSFont = "<UICTFont: 0x7fa470451e90> font-family: \"Times New Roman\"; font-weight: normal; font-style: normal; font-size: 40.00pt";
    NSKern = 0;
    NSParagraphStyle = "Alignment 4, LineSpacing 0, ParagraphSpacing 0, ParagraphSpacingBefore 0, HeadIndent 0, TailIndent 0, FirstLineHeadIndent 0, LineHeight 0/0, LineHeightMultiple 0, LineBreakMode 0, Tabs (\n), DefaultTabInterval 36, Blocks (null), Lists (null), BaseWritingDirection 0, HyphenationFactor 0, TighteningFactor 0, HeaderLevel 0";
    NSStrokeColor = "UIDeviceRGBColorSpace 0 0 0 1";
    NSStrokeWidth = 0;
}

To resolve the issue, simply remove the NSKern property altogether:

NSMutableAttributedString *mutableAttributedString = [attrString mutableCopy];
[mutableAttributedString removeAttribute:NSKernAttributeName 
                                   range:NSMakeRange(0, [mutableAttrString length])];

Note that the text-rendering: optimizeLegibility; does not appear to have any impact, so it can be ommitted.