let bodyFontDescriptor = UIFontDescriptor .preferredFontDescriptor(withTextStyle: UIFontTextStyle.body) let bodyMonospacedFontDescriptor = bodyFontDescriptor.addingAttributes( [ UIFontDescriptorFeatureSettingsAttribute: [ [ UIFontFeatureTypeIdentifierKey: kTextSpacingType,UIFontFeatureSelectorIdentifierKey: kMonospacedTextSelector ] ] ]) let bodyMonospacedFont = UIFont(descriptor: bodyMonospacedFontDescriptor,size: 0.0) textview.font = bodyMonospacedFont
这将生成带有可变宽度字符的文本.
我需要获得一个monospace字体,而不需要硬编码快递
和固定的大小.
部署目标是ios 9.0
解决方法
这是UIFontDescriptor的扩展,它返回给定文本样式的首选等宽字体描述符.使用UIFont或UIFontDescriptor获取完全等宽字体没有简单的方法.该解决方案试图找到一个好的等宽字体,并在需要时回退到Courier.
extension UIFontDescriptor { static let monoDescriptor: UIFontDescriptor = { // Attempt to find a good monospaced,non-bold,non-italic font for family in UIFont.familyNames { for name in UIFont.fontNames(forFamilyName: family) { let f = UIFont(name: name,size: 12)! let fd = f.fontDescriptor let st = fd.symbolicTraits if st.contains(.traitMonoSpace) && !st.contains(.traitBold) && !st.contains(.traitItalic) && !st.contains(.traitExpanded) && !st.contains(.traitCondensed) { return fd } } } return UIFontDescriptor(name: "Courier",size: 0) // fallback }() class func preferredMonoFontDescriptor(withTextStyle style: UIFontTextStyle) -> UIFontDescriptor { // Use the following line if you need a fully monospaced font let monoDescriptor = UIFontDescriptor.monoDescriptor // Use the following two lines if you only need monospaced digits in the font //let monoDigitFont = UIFont.monospacedDigitSystemFont(ofSize: 0,weight: .regular) //let monoDescriptor = monoDigitFont.fontDescriptor // Get the non-monospaced preferred font let defaultFontDescriptor = preferredFontDescriptor(withTextStyle: style) // Remove any attributes that specify a font family or name and remove the usage // This will leave other attributes such as size and weight,etc. var fontAttrs = defaultFontDescriptor.fontAttributes fontAttrs.removeValue(forKey: .family) fontAttrs.removeValue(forKey: .name) fontAttrs.removeValue(forKey: .init(rawValue: "NSCTFontUIUsageAttribute")) let monospacedFontDescriptor = monoDescriptor.addingAttributes(fontAttrs) return monospacedFontDescriptor.withSymbolicTraits(defaultFontDescriptor.symbolicTraits) ?? monospacedFontDescriptor } }
请注意有关是否需要完全等宽字体的字体或仅具有等宽数字的字体的注释.评论/取消注释这些行以满足您的特定需求.
样品用法:
let bodyMonospacedFont = UIFont(descriptor: .preferredMonoFontDescriptor(withTextStyle: .body),size: 0) textview.font = bodyMonospacedFont
以下是一些测试代码,用于确认preferredMonoFontDescriptor(withTextStyle :)的结果适用于所有样式:
let textStyles: [UIFontTextStyle] = [ .body,.callout,.caption1,.caption2,.footnote,.headline,.subheadline,.largeTitle,.title1,.title2,.title3 ] for style in textStyles { let nfont = UIFont(descriptor: .preferredFontDescriptor(withTextStyle: style),size: 0) let mfont = UIFont(descriptor: .preferredMonoFontDescriptor(withTextStyle: style),size: 0) print(style) print(nfont) print(mfont) }
如果比较每对结果,它们具有相同的大小,重量和样式,只是不同的字体.