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?
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With