UITextView with custom font not working when text set to "attributed"

12.4k views Asked by At

I have a UITextView with some text that came from a .rtf (pasted directly onto Xcode)

The context contain only one custom font (Futura Book BT 11.0)

If I set the "text(attributed)" property to "plain"= The custom font appear properly from the storyboard and from the app

If I set the "text" property to "attributed"=. The custom font appear properly from the storyboard BUT not from the app.

As my goal was to have a text with multiple font working, how to have the attributed property to work with custom fonts? (Swift)

Thanks!

11

There are 11 answers

0
Ishara Meegahawala On

There is a workaround. Just double click on font file(in Finder) and install it in to system.

0
Nikola Jovic On

Please call all your code in viewDidLayoutSubviews method! Than works. I have many problems when chanhing font size, style i viewDidLoad or viewWillApperar methods.

So just move your code in viewDidLayoutSubviews method. You can use flag to change fonts only once since this method can be called many times :]

0
Fadi On

✅FIXED :

Fixed by subclassing my UITextView as KMPlaceholderTextView which is also useful for adding a placeholder to text view and can be used from Interface Builder as same as UITextField.

Now I can use custom fonts successfully and add placeholder text.

0
Nilesh R Patel On

You can use this extension

extension NSMutableAttributedString {

    func createAttributedString(word : NSArray, attributeCustomizeFont:UIFont, defaultFont : UIFont, defaultColor : UIColor, allowSpecing : Bool , allowUnderLine : Bool = false) -> NSAttributedString {

        self.addAttribute(NSAttributedString.Key.font, value: defaultFont, range: (self.string as NSString).range(of: self.string))
        if allowSpecing {
            self.addAttribute(NSAttributedString.Key.kern, value: NSNumber(value: 5), range: (self.string as NSString).range(of: self.string))
        }else {
            self.addAttribute(NSAttributedString.Key.kern, value: NSNumber(value: 0), range: (self.string as NSString).range(of: self.string))
        }

        self.addAttribute(NSAttributedString.Key.foregroundColor, value: defaultColor, range: (self.string as NSString).range(of: self.string))

        for i in 0..<word.count {
            self.addAttribute(NSAttributedString.Key.font, value: attributeCustomizeFont, range: (self.string as NSString).range(of: word.object(at: i) as! String))

        }
        if allowUnderLine {
            self.addAttribute(NSAttributedString.Key.underlineStyle, value: NSUnderlineStyle.single.rawValue, range: (self.string as NSString).range(of: self.string))
        }
        return self
    }
}

How to use extension

var attributedString = NSMutableAttributedString(string:"Test for set custom font")
        attributedString = attributedString.createAttributedString(word: ["custom font"], attributeCustomizeFont: UIFont(name: "Arial", size: 18)! , defaultFont: UIFont(name: "Helvetica", size: 15)!, defaultColor: UIColor.black, allowSpecing: false) as! NSMutableAttributedString

So the whole string font set 'Helvetica' with size 18 and for 'custom font' text set 'Arial' font with size 15.

2
AngelMixu On

In my case the problem was that I didn't have the font installed on my system, so I did it with Font Book. Then, the font appeared on the list in attributed text labels.

EDIT: Now I had some problems for displaying my current text and did this (I'm using a UILabel, not tested on UITextView):

My solution is to create an attributed string from html (saw this extension somewhere here in SO):

extension String {
    var html2AttStr: NSAttributedString? {
        guard let data = dataUsingEncoding(NSUTF8StringEncoding) else { return nil }
        do {
            return try NSAttributedString(data: data,
                                          options: [
                                            NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
                                            NSCharacterEncodingDocumentAttribute: NSUTF8StringEncoding],
                                          documentAttributes: nil)
        } catch let error as NSError {
            //print(error.code)
            return nil
        }
    }
}

And then what I do is something like:

let htmlStyle = "<meta charset=\"UTF-8\"><style> body { font-family: 'SourceSansPro-Light'; font-size: 18px; text-align: center; } b {font-family: 'SourceSansPro-Light'; }</style>"
let myString = "<font size=\"+2\">Slightly bigger font</font><br><br>Some message with normal text <b>a bold text</b> and some more text"
var attributedString = htmlStyle
attributedString.appendContentsOf(myString)
informationLabel.attributedText = attributedString.html2AttStr

One of the advantages of this is that I can now put some '%s' text inside the string for parsing with a word/number/etc. and It's easier to translate and parse. With formatted text I had to make a bunch of code for finding text, applying format without touching anything around. This works pretty well for me :)

4
Orion On

What I do:

private var _mutableString: NSMutableAttributedString!

if !isTitle {
    var titleFont: UIFont = UIFont(name: StyleGlobals.TitleFontName, size: StyleGlobals.TitleFontSize)!
    self._mutableString.addAttribute(NSFontAttributeName, value: titleFont, range: NSMakeRange(0, count(self._mutableString.string)))
    self._mutableString.addAttribute(NSForegroundColorAttributeName, value: StyleGlobals.FontColor, range: NSMakeRange(0, count(self._mutableString.string)))
}

self.Label.attributedText = self._mutableString

This applies both a new font color as well as the font itself. I have a certain UILabel that is has to be able to contain different fonts. It can either be a Title or a subtitle. Hence I had to apply the font when I had determined what the Label is going to contain.

1
freytag On

Did you make sure that "Futura Book BT" is correctly added as a custom font in your app?

4
scott On

The custom font appear properly from the storyboard BUT not from the app.

Does the app not show the font at all, or does it restore to system font? If it is reverting to Helvetica, it looks like this may be a known bug in iOS 8.1 http://openradar.appspot.com/radar?id=5117089870249984

Possible Solution: Did you test it on the simulator and a device? It could be that it just doesn't work on the simulator, which means you could fix it by installing the font on your system.

0
Ali Farhan On

I used the different font sizes but still facing the issues. Then i changed the text alignment to left instead of justified. Then it worked fine.

0
SaRaVaNaN DM On

Making UITextview "selectable" from storyboard will work.

2
Bilal Ahmad On

I have faced the same problem when I used multiple custom fonts in attributed UILabel. Storyboard shows correct result but device does not!!

What I have find out that if the font size is different of text with different custom fonts. It works fine!!

So for now I use font size with minor difference. Like if one is 14 I used 14.01 for the other. Its not possible inside storyboard so I opened storyboard as source code and manually set font size like:

<attributedString key="attributedTitle">    
  <fragment content="Do not have account? ">
      <attributes>
        <color key="NSColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="calibratedRGB"/>
        <font key="NSFont" size="14" name="Roboto-Light"/>
        <paragraphStyle key="NSParagraphStyle" alignment="center" lineBreakMode="wordWrapping" baseWritingDirection="natural" tighteningFactorForTruncation="0.0"/>
      </attributes>
    </fragment>
    <fragment content="Login">
      <attributes>
        <color key="NSColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="calibratedRGB"/>
        <font key="NSFont" size="14.01" name="Roboto-Bold"/>
        <paragraphStyle key="NSParagraphStyle" alignment="center" lineBreakMode="wordWrapping" baseWritingDirection="natural" tighteningFactorForTruncation="0.0"/>
      </attributes>
    </fragment>
<attributedString key="attributedTitle">

But still I am unable to find why it happens!