Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS - How can I set a fallback font for my custom font?

I'm using a bold custom font for my app's navigation bar titles.

I've also just localised my app. For languages the font doesn't support (primarily Asian languages), iOS falls back to the system default - alas, this is not a bold system default but a standard weighting not suitable for headings.

What can I do to change this?

like image 257
Jordan Smith Avatar asked Jan 23 '14 04:01

Jordan Smith


1 Answers

Answer to the bounty question

Here is an extension allowing to construct NSAttributedString with a second set of attributes that will be applied to latin characters:

extension String {
    private var englishRanges: [NSRange] {
        let set = NSMutableCharacterSet(range: NSRange(location: 0x0041, length: 26))
        set.addCharactersInRange(NSRange(location: 0x0061, length: 26))
        var start = startIndex
        var englishRanges = [Range<String.Index>]()
        while let range = rangeOfCharacterFromSet(set, options: [], range: start..<endIndex) {
            start = range.endIndex
            englishRanges.append(range)
        }
        return englishRanges.map {NSRange(location: startIndex.distanceTo($0.startIndex), length: $0.count)}
    }

    func attributedMultilanguageString(options: [String:AnyObject], englishOptions:[String:AnyObject]) -> NSAttributedString {
        let string = NSMutableAttributedString(string: self, attributes: options)
        englishRanges.forEach {
            string.setAttributes(englishOptions, range: $0)
        }
        return string
    }
}

Example usage:

let font = UIFont(name: "Arial-BoldMT", size: 18.0)!
let englishFont = UIFont(name: "Chalkduster", size: 18.0)!
let label = UILabel()
label.attributedText = "some string 111".attributedMultilanguageString([ NSFontAttributeName: font], englishOptions: [ NSFontAttributeName: englishFont])

Second approach

And this extension allows you to specify fallback font instead of using a second font for specific characters:

extension String {
    private func unsupportedCharacterIndexes(font: String) -> [String.Index] {
        let font = CGFontCreateWithFontName(font)
        return characters.indices.filter {CGFontGetGlyphWithGlyphName(font, String(self[$0])) == 0}
    }

    func attributedString(fontName: String, fallbackFontName: String, fontSize: CGFloat, options: [String:AnyObject]? = nil) -> NSAttributedString {
        var options = options ?? [String:AnyObject]()
        options[NSFontAttributeName] = UIFont(name: fontName, size: fontSize)
        let string = NSMutableAttributedString(string: self, attributes: options)
        options[NSFontAttributeName] = UIFont(name: fallbackFontName, size: fontSize)
        unsupportedCharacterIndexes(fontName).forEach {
            string.setAttributes(options, range: NSRange(location: startIndex.distanceTo($0), length: 1))
        }
        return string
    }
}

Example usage:

let label = UILabel()
label.attributedText = "some текст".attributedString("Chalkduster", fallbackFontName: "Baskerville-SemiBoldItalic", fontSize: 18)
like image 165
bzz Avatar answered Sep 27 '22 19:09

bzz