Swift 3.1 - NSSuperScript in NSAttributedString not working as expected
Asked Answered
D

1

1

The application I am working on encountered an issue when testing with iOS 10.3 Simulator via XCode 8.3 beta 2, where the superscript in AttributedString displayed on the same line with normal text. For iOS 10.2.x and below, it is displaying correctly.

iOS 10.3 screenshot: https://www.dropbox.com/s/p5v71g722cg5qhy/Screen%20Shot%202017-02-21%20at%2010.24.21%20AM.png?dl=0

iOS 10.2.x and below screenshot: https://www.dropbox.com/s/lcfsic6xyz953qp/Screen%20Shot%202017-02-21%20at%2010.19.17%20AM.png?dl=0

Here's how I handled the text:

  • Initially, the string is in HTML format, and tag for the text "8,9" above

<html>  
<head>  
     <style> body { color: #554344 ; font-family: \'MyCustomFont\'; font-size: 18px; } sup { font-size: 13px; } </style>  
</head>  
<body>  
     ABCdef<sup>1,2,3,8,9</sup>  
</body>  
</html>  
  • The html string then converted into NSAttributedString using the following script

private func convertHTMLToAttributedString(string: String) -> NSAttributedString {  
       guard let data = string.data(using: String.Encoding.utf16, allowLossyConversion: false) else { return NSAttributedString() }  
       return try! NSAttributedString(  
           data: data,  
           options: [ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType],  
           documentAttributes: nil)  
   } 
  • The NSAttributedString then will be rendered via UILabel.attributedText This is the attributedText description:

1,2,3,8,9{  
   NSColor = "kCGColorSpaceModelRGB 0.333333 0.262745 0.266667 1 ";  
   NSFont = "<UICTFont: 0x7fed0a469880> font-family: \"MyCustomFont\"; font-weight: normal; font-style: normal; font-size: 10.00pt";  
   NSKern = 0;  
   NSParagraphStyle = "Alignment 4, LineSpacing 0, ParagraphSpacing 0, ParagraphSpacingBefore 0, HeadIndent 0, TailIndent 0, FirstLineHeadIndent 0, LineHeight 13/0, LineHeightMultiple 0, LineBreakMode 0, Tabs (\n), DefaultTabInterval 36, Blocks (\n), Lists (\n), BaseWritingDirection 0, HyphenationFactor 0, TighteningForTruncation NO, HeaderLevel 0";  
   NSStrokeColor = "kCGColorSpaceModelRGB 0.333333 0.262745 0.266667 1 ";  
   NSStrokeWidth = 0;  
   NSSuperScript = 1;  
}

Note: I thought the issue was related to our custom font, but the issue still happen when we use the default font.

Is this an issue related with Swift 3.1 and should be fixed?

Doubleacting answered 27/2, 2017 at 5:53 Comment(1)
I recently discovered the same effect (NSSuperScript seems to have no effect) within an macOS app.Cumulation
S
1

We found that it's an issue in UILabel's attributed text rendering in iOS 10.3, not Swift 3.1-related. Affected strike-through style for us.

For our specific scenario (we have all attributes specified in NSAttributedString, not using UILabel's properties) this is the solution:

/// This UILabel subclass accomodates conditional fix for NSAttributedString rendering broken by Apple in iOS 10.3
final class PriceLabel: UILabel {

    override func drawText(in rect: CGRect) {
        guard let attributedText = attributedText else {
            super.drawText(in: rect)
            return
        }

        if #available(iOS 10.3, *) {
            attributedText.draw(in: rect)
        } else {
            super.drawText(in: rect)
        }
    }
}
Shrink answered 28/3, 2017 at 15:53 Comment(3)
Even though my label only has set the text property, attributedText is not nil (it contains the same string, plus attributes for NSColor, NSFont, and NSParagraphStyle). Therefore the guard statement in the above code always returns true.Eli
@Koen it's not guaranteed to be non-nil though. Who knows what they might change in the subsequent iOS version or if it was non-nil pre-iOS 10.Shrink
Yeah, good point. Still interesting why attributedText gets set when only text is set. But that's outside the scope of this question.Eli

© 2022 - 2024 — McMap. All rights reserved.