IOS Swift adds custom weight to the font descriptor

It seems like it should be rudimentarily easy, but for some reason it doesn't work. I read similar posts in SO, and it seems like there might be a problem with the Font Dictionary? Is this a problem, or am I just missing something? This is my first time messing around with such fonts, so I think this might be the last one.

I do not want to use constants or provide the font with a β€œ-larger” option. I would like to have fine control over the font.

let traits = [UIFontWeightTrait : 1.0] imgFontDescriptor = UIFontDescriptor(fontAttributes: [UIFontDescriptorNameAttribute: "Helvetica"]) imgFontDescriptor = imgFontDescriptor.fontDescriptorByAddingAttributes([UIFontDescriptorTraitsAttribute:traits]) imgTextFont = UIFont(descriptor: imgFontDescriptor!, size: 24.0) 

Study:

Font descriptor returns nil in iOS 8

https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIFontDescriptor_Class/#//apple_ref/doc/constant_group/Font_Traits_Dictionary_Keys

According to iOS docs using the value of number should work (I am running iOS 9.2):

UIFontWeightTrait The normalized weight value as an NSNumber object. The valid value range is -1.0 to 1.0. A value of 0.0 corresponds to regular or average font weight. You can also use the font weight constant to specify a specific weight; for a list of constants you can use, see Font Weights. Available in iOS 7.0 and later.

+5
source share
2 answers

UIFont(descriptor: imgFontDescriptor!, size: 24.0) returns a font that matches the descriptor. If it cannot find a font match with your description, it returns the default font. Therefore, you cannot control your weight manually. It depends on which font you are using. If Font maintains this weight, it will return it.

One more thing you should use [UIFontDescriptorFamilyAttribute: "Helvetica"] . Thus, it will define the FontName database on FamilyName and your FontWeight.

The correct way to use const from Apple lib:

 public let UIFontWeightUltraLight: CGFloat @available(iOS 8.2, *) public let UIFontWeightThin: CGFloat @available(iOS 8.2, *) public let UIFontWeightLight: CGFloat @available(iOS 8.2, *) public let UIFontWeightRegular: CGFloat @available(iOS 8.2, *) public let UIFontWeightMedium: CGFloat @available(iOS 8.2, *) public let UIFontWeightSemibold: CGFloat @available(iOS 8.2, *) public let UIFontWeightBold: CGFloat @available(iOS 8.2, *) public let UIFontWeightHeavy: CGFloat @available(iOS 8.2, *) public let UIFontWeightBlack: CGFloat*/ 

You must use http://iosfonts.com/ to determine how much weight the font supports this name.

In the case of Helvetica:

 let traits = [UIFontWeightTrait : UIFontWeightLight] // UIFontWeightBold / UIFontWeightRegular var imgFontDescriptor = UIFontDescriptor(fontAttributes: [UIFontDescriptorFamilyAttribute: "Helvetica"]) imgFontDescriptor = imgFontDescriptor.fontDescriptorByAddingAttributes([UIFontDescriptorTraitsAttribute:traits]) 
+8
source

If you use an existing fontDescriptor (for example, from an existing font), it may not work due to the explicit attribute ".name" in the font Descriptor.fontAttributes.

Solution that works for me (Swift 4):

 extension UIFont { var bold: UIFont { return withWeight(.bold) } var semibold: UIFont { return withWeight(.semibold) } private func withWeight(_ weight: UIFont.Weight) -> UIFont { var attributes = fontDescriptor.fontAttributes var traits = (attributes[.traits] as? [UIFontDescriptor.TraitKey: Any]) ?? [:] traits[.weight] = weight attributes[.name] = nil attributes[.traits] = traits attributes[.family] = familyName let descriptor = UIFontDescriptor(fontAttributes: attributes) return UIFont(descriptor: descriptor, size: pointSize) } } 

Using:

 let baseFont = UIFont(name: "American Typewriter", size: 20)! let boldFont = baseFont.bold let semibold = baseFont.semibold 
0
source

Source: https://habr.com/ru/post/1239758/


All Articles