How can I get weight of a UILabel?
Asked Answered
S

5

12

User from storyboard or programatically can set font weight as regular, semi bold etc.

I want to read weight for any font label.

I tried po label.font.description and font-weight is there and but there is no exposed variable to get weight from font.

Is it possible?

Seato answered 8/2, 2018 at 13:13 Comment(3)
label.font.UIFontWeightTrypanosomiasis
I don't think it is possible to get weight. you can just check it is bold or not.Shashaban
May be This use full:- developer.apple.com/documentation/uikit/…Pteropod
E
12

To get the font weight string name, use the font descriptor and pass in the face attribute.

Swift 4.2

let font = UIFont.systemFont(ofSize: 14, weight: UIFont.Weight.bold)
let face = font.fontDescriptor.object(forKey: UIFontDescriptorFaceAttribute) as! String
print("face: \(face)")

Swift 3

let font = UIFont.systemFont(ofSize: 14, weight: UIFontWeightBold)
let face = font.fontDescriptor.object(forKey: UIFontDescriptorFaceAttribute) as! String
print("face: \(face)")
Elconin answered 8/2, 2018 at 14:48 Comment(1)
UIFontDescriptorFaceAttribute has been renamed to UIFontDescriptor.AttributeName.face (or just .face) in later versions of Swift.Ganger
G
20

It seems that fontDescriptor.fontAttributes won't return all the attributes of a font. Luckily fontDescriptor.object(forKey: .traits) will, so we can hop onto that.

Newer Swift versions:

extension UIFont {
    var weight: UIFont.Weight {
        guard let weightNumber = traits[.weight] as? Double else { return .regular }
        let weight = UIFont.Weight(rawValue: weightNumber)
        return weight
    }

    private var traits: [UIFontDescriptor.TraitKey: Any] {
        return fontDescriptor.object(forKey: .traits) as? [UIFontDescriptor.TraitKey: Any]
            ?? [:]
    }
}

Older Swift versions:

extension UIFont {
    var weight: UIFont.Weight {
        guard let weightNumber = traits[.weight] as? NSNumber else { return .regular }
        let weightRawValue = CGFloat(weightNumber.doubleValue)
        let weight = UIFont.Weight(rawValue: weightRawValue)
        return weight
    }

    private var traits: [UIFontDescriptor.TraitKey: Any] {
        return fontDescriptor.object(forKey: .traits) as? [UIFontDescriptor.TraitKey: Any]
            ?? [:]
    }
}

and then it's as simple as label.font.weight

(This is fundamentally equivalent to https://mcmap.net/q/889130/-how-can-i-get-weight-of-a-uilabel but it uses UIKit APIs)

Godspeed answered 17/12, 2018 at 15:29 Comment(1)
Elegant. I added a var to the extension to convert an IB-defined system font to its monospaceDigit equivalent, something I'd been fighting for a while. Thanks. Can't do code here, but the meat: return UIFont.monospacedDigitSystemFont(ofSize: self.pointSize, weight: self.weight)Rahmann
E
12

To get the font weight string name, use the font descriptor and pass in the face attribute.

Swift 4.2

let font = UIFont.systemFont(ofSize: 14, weight: UIFont.Weight.bold)
let face = font.fontDescriptor.object(forKey: UIFontDescriptorFaceAttribute) as! String
print("face: \(face)")

Swift 3

let font = UIFont.systemFont(ofSize: 14, weight: UIFontWeightBold)
let face = font.fontDescriptor.object(forKey: UIFontDescriptorFaceAttribute) as! String
print("face: \(face)")
Elconin answered 8/2, 2018 at 14:48 Comment(1)
UIFontDescriptorFaceAttribute has been renamed to UIFontDescriptor.AttributeName.face (or just .face) in later versions of Swift.Ganger
P
10

Try following sample font extension with Swift 4. (It needs some improvement for all types of font weights)

extension UIFont {

    func getFontWeight() -> UIFont.Weight {
    
        let fontAttributeKey = UIFontDescriptor.AttributeName.init(rawValue: "NSCTFontUIUsageAttribute")
        if let fontWeight = self.fontDescriptor.fontAttributes[fontAttributeKey] as? String {
            switch fontWeight {

            case "CTFontBoldUsage":
                return UIFont.Weight.bold
        
            case "CTFontBlackUsage":
                return UIFont.Weight.black
        
            case "CTFontHeavyUsage":
                return UIFont.Weight.heavy
        
            case "CTFontUltraLightUsage":
                return UIFont.Weight.ultraLight
        
            case "CTFontThinUsage":
                return UIFont.Weight.thin
        
            case "CTFontLightUsage":
                return UIFont.Weight.light
        
            case "CTFontMediumUsage":
                return UIFont.Weight.medium
        
            case "CTFontDemiUsage":
                return UIFont.Weight.semibold
        
            case "CTFontRegularUsage":
                return UIFont.Weight.regular

            default:
                return UIFont.Weight.regular
            }
        }
        
    return UIFont.Weight.regular
}

Try with label:

let label = UILabel()
var fontWeight = label.font.getFontWeight()
print("fontWeight - \(fontWeight)")

label.font = UIFont.systemFont(ofSize: 14, weight: UIFont.Weight.bold)
fontWeight = label.font.getFontWeight()
print("fontWeight - \(fontWeight)")

label.font = UIFont.systemFont(ofSize: 14, weight: UIFont.Weight.black)
fontWeight = label.font.getFontWeight()
print("fontWeight - \(fontWeight)")

label.font = UIFont.systemFont(ofSize: 14, weight: UIFont.Weight.heavy)
fontWeight = label.font.getFontWeight()
print("fontWeight - \(fontWeight)")

label.font = UIFont.systemFont(ofSize: 14, weight: UIFont.Weight.ultraLight)
fontWeight = label.font.getFontWeight()
print("fontWeight - \(fontWeight)")

label.font = UIFont.systemFont(ofSize: 14, weight: UIFont.Weight.thin)
fontWeight = label.font.getFontWeight()
print("fontWeight - \(fontWeight)")

label.font = UIFont.systemFont(ofSize: 14, weight: UIFont.Weight.light)
fontWeight = label.font.getFontWeight()
print("fontWeight - \(fontWeight)")

label.font = UIFont.systemFont(ofSize: 14, weight: UIFont.Weight.medium)
fontWeight = label.font.getFontWeight()
print("fontWeight - \(fontWeight)")

label.font = UIFont.systemFont(ofSize: 14, weight: UIFont.Weight.semibold)
fontWeight = label.font.getFontWeight()
print("fontWeight - \(fontWeight)")

Here is Apple document for list of Font Weights

The value of this weight is an NSNumber object. The valid value range is from -1.0 to 1.0. The value of 0.0 corresponds to the regular or medium font weight. You can also use a font weight constant to specify a particular weight.

Pesce answered 8/2, 2018 at 15:20 Comment(0)
M
3

You can play around with font's symbolic traits:

// is true when font is bold
label.font.fontDescriptor.symbolicTraits.contains(UIFontDescriptorSymbolicTraits.traitBold)

Check docs for more traits.

Mccandless answered 8/2, 2018 at 13:20 Comment(1)
this is working when I am checking for bold and italic style. But there is no UIFontDescriptorSymbolicTraits for semibold.Seato
S
3

It seems that there is no direct way to get it. As a workaround, You could get an indication of what's the weight of the font as follows:

let labelFont = label.font as CTFont
if let fontTraits = CTFontCopyTraits(labelFont) as? [CFString: CFNumber], let fontWeight = fontTraits[kCTFontWeightTrait] {
    print(fontWeight)
}

The UIFont has been casted as CTFont, which generates CFDictionary (by using CTFontCopyTraits(_:)) that contains the value of kCTFontWeightTrait. Note that it would not know what is the exact font weight, nevertheless it could be somehow useful to an indication of what is the weight:

Key to access the normalized weight trait from the font traits dictionary. The value returned is a CFNumber representing a float value between -1.0 and 1.0 for normalized weight. The value of 0.0 corresponds to the regular or medium font weight.

Soekarno answered 8/2, 2018 at 14:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.