Reputation: 127
I've migrated project from swift 3 to swift 4 and cannot find a info how to get a font attribute from a UIFontDescriptor
. Here is the code which works perfect in swift 3 :
@objc convenience init(myCoder aDecoder: NSCoder) {
if let fontDescriptor = aDecoder.decodeObject(forKey: "UIFontDescriptor") as? UIFontDescriptor {
if let fontAttribute = fontDescriptor.fontAttributes["NSCTFontUIUsageAttribute"] as? String {
var fontName = ""
switch fontAttribute {
case "CTFontRegularUsage":
fontName = Roboto.regular.rawValue
case "CTFontEmphasizedUsage", "CTFontBoldUsage":
fontName = Roboto.bold.rawValue
default:
fontName = Roboto.regular.rawValue
}
self.init(name: fontName, size: fontDescriptor.pointSize)!
}
else {
self.init(myCoder: aDecoder)
}
}
else {
self.init(myCoder: aDecoder)
}
}
But In swift 4 the line :
if let fontAttribute = fontDescriptor.fontAttributes["NSCTFontUIUsageAttribute"] as? String
has an error : Ambiguous reference to member 'subscript'
.
Any ideas how can I change it ?
Thanks!
Upvotes: 3
Views: 4147
Reputation: 452
This work for me, creating a static value nsctFontUIUsage for NSCTFontUIUsageAttribute
to then use it in fontDescriptor.fontAttributes[.nsctFontUIUsage]
:
extension UIFontDescriptor.AttributeName {
static let nsctFontUIUsage = UIFontDescriptor.AttributeName(rawValue: "NSCTFontUIUsageAttribute")
}
extension UIFont {
@objc convenience init(myCoder aDecoder: NSCoder) {
guard
let fontDescriptor = aDecoder.decodeObject(forKey: "UIFontDescriptor") as? UIFontDescriptor,
let fontAttribute = fontDescriptor.fontAttributes[.nsctFontUIUsage] as? String else {
self.init(myCoder: aDecoder)
return
}
var fontName = ""
switch fontAttribute {
case "CTFontRegularUsage":
fontName = Resources.Fonts.Weight.regular
case "CTFontEmphasizedUsage", "CTFontBoldUsage":
fontName = Resources.Fonts.Weight.semibold
case "CTFontObliqueUsage":
fontName = Resources.Fonts.Weight.italic
default:
fontName = Resources.Fonts.Weight.light
}
self.init(name: fontName, size: fontDescriptor.pointSize)!
}
}
Upvotes: 2
Reputation: 467
1) Be sure all your Project / Target Build Settings show Swift Language Version 4.x (4.0 for now). Without this set, the new UIFontDescriptor values won't be available. Note: a project with multiple targets may misbehave depending on which target you have selected and the Swift version specified for that target. To avoid, be sure all targets are updated to Swift 4.0.
2) Access a specific UIFontAttribute using the built in static types, paying attention to the expected return types.
For a UIFontAttribute with an optional NSString return type:
let fontAttribute = fontDescriptor.object(forKey: .face) as? String
or in your example, where no built-in static types exist:
let fontAttribute = fontDescriptor.object(forKey: UIFontDescriptor.AttributeName(rawValue: "NSCTFontUIUsageAttribute")) as? String
Upvotes: 1
Reputation: 1
Here is my Solution. Work for me
@objc convenience init(myCoder aDecoder: NSCoder) {
if let fontDescriptor = aDecoder.decodeObject(forKey: "UIFontDescriptor") as? UIFontDescriptor {
let fontAttribute = UIFontDescriptor.AttributeName("NSCTFontUIUsageAttribute")
if let fontAttribute = fontDescriptor.fontAttributes[fontAttribute] as? String {
var fontName = ""
switch fontAttribute {
case "CTFontRegularUsage":
fontName = Roboto.regular.rawValue
case "CTFontEmphasizedUsage", "CTFontBoldUsage":
fontName = Roboto.bold.rawValue
default:
fontName = Roboto.regular.rawValue
}
self.init(name: fontName, size: fontDescriptor.pointSize)!
}
else {
self.init(myCoder: aDecoder)
}
}
else {
self.init(myCoder: aDecoder)
}
}
Upvotes: 0
Reputation: 535231
It looks like you're trying to treat your custom font as a dynamic type font. The supported way to do that in iOS 11 is to use UIFontMetrics.
Upvotes: 1
Reputation: 9040
let font: UIFont
let fontAttribute = UIFontDescriptor.AttributeName("NSCTFontUIUsageAttribute")
let fontUsageAttribute = font.fontDescriptor.fontAttributes[fontAttribute] as? String
Upvotes: 2