IOS How to set backup font for my custom font?

I use a bold custom font for headings in the app navigation bar.

I also just localized my application. For languages ​​that do not support the font (mainly Asian languages), iOS returns to the system by default - alas, this is not bold by default, and the standard weight is not suitable for headings.

What can I do to change this?

+7
ios objective-c iphone localization
source share
5 answers

Answer the question of generosity

Here is an extension that allows you to build an 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 } } 

Usage example:

 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 a fallback font instead of a second font for certain 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 } } 

Usage example:

 let label = UILabel() label.attributedText = "some ".attributedString("Chalkduster", fallbackFontName: "Baskerville-SemiBoldItalic", fontSize: 18) 
+2
source share

I'm not sure if this is the best way, but I am using the following snippet to test certain languages:

 //store all fallback languages in this array (eg.: el = greek, ru = russian) NSArray *fallbackFont = @[@"el", @"ru"]; NSString *lang = [[NSLocale preferredLanguages] objectAtIndex:0] BOOL hasFallbackFont = [fallbackFont containsObject:lang]; NSString *fontNameBold = hasFallbackFont ? @"Fallback-Font-Bold" : @"Regular-Font-Bold"; ... myLabel.font = [UIFont fontWithName:fontNameBold size:12.0]; 
0
source share

The basic one, of course, is ordinary if you replace the custom font, if the language is not supported. In other words, the task is to find out if a given language is supported or not.

Not the sexiest of the solutions, but I believe it should work:

  • Convert font to CGFontRef. CGFontRef cgFontVersion = CGFontCreateWithFontName((CFStringRef)uiFont.fontName);
  • use CGFontGetGlyphWithGlyphName to an array containing the necessary glyphs from each language that you plan to support. *
  • If CGFontGetGlyphWithGlyphName returns 0, your own font is NOT supported, and you can use any return font you want.

* obtaining this data can be the most difficult part, the pleasant part that you would need to do only once and use it again for future projects ...

A more pragmatic solution would be to make something like Hannes, but then you will need to redo it for each language manually for each new custom font that you decide to use in the future.

0
source share
 + (UIFont *)addFallbacktoFont:(UIFont*)font{ UIFontDescriptor* originalDescriptor = [font fontDescriptor]; UIFontDescriptor* fallbackDescriptor = [originalDescriptor fontDescriptorByAddingAttributes:@{UIFontDescriptorNameAttribute:@"Helvetica Neue"}]; UIFontDescriptor* repaired = [originalDescriptor fontDescriptorByAddingAttributes:@{UIFontDescriptorCascadeListAttribute:@[ fallbackDescriptor ]}]; font = [UIFont fontWithDescriptor:repaired size:0.0]; return font; } 

Change “Helvetica Neue” to any font name that you want to fall back and you will get a backup font.

0
source share

Please make sure that you have the correct font that you want to display as the default font, and not the default for the system. But, something similar to the desired font, by default.

 // Method that returns the font for buttons and title bar // Pass in your custom font as a string argument/ parameter func getFont(fontName: String, size fontSize: CGFloat)-> UIFont { // Unwrap your custom font here, if font exists "Hooray!" else "Bo-Oh!" return a default one if let customFont = UIFont(named: fontName, size: fontSize ) { return customFont } else { // This gets the system default font and returns to you! return UIFont(named: defaultFont, size: fontSize ) } 

This ensures that we will always use the font. Now you can take the rest from here, how to adjust the font and its style to the preferred look / controls.

That should do it. Tell us how it goes for you!

-one
source share

All Articles