如何获取 UIFont 的百分比 lineSpacing? (计算百分比值)
How to get percentage lineSpacing of UIFont? (to calculate a percentage value)
有没有办法将 lineSpacing
property of NSParagraphStyle
/ NSMutableParagraphStyle
attribute of an NSAttributedString
对象设置为字体 base/original lineSpacing
的百分比?
lineSpacing
是 NSParagraphStyle
的 属性 而不是 UIFont
,因此不可能知道字体的原始 lineSpacing
是什么。
作为参考,这是我写的一个小扩展,用于将 lineSpacing
分配给 UILabel
(累积,不会导致标签的 attributedString 上的信息丢失):
import UIKit
extension UILabel {
/// -important: must be called after setting the `text` property so the computed NSRange would be valid
func setLineSpacing(with lineSpacing: CGFloat) {
// get safe string
guard let textString = self.text, !textString.isEmpty
else { return }
// get the range
let entireRange: NSRange = (textString as NSString).range(of: textString)
guard entireRange.isValidNSRange(within: textString)
else { assertionFailure() ; return }
// NSMutableAttributedText
guard let mutableAttributedText: NSMutableAttributedString = self.attributedText?.mutableCopy() as? NSMutableAttributedString
else { assertionFailure() ; return }
// NSParagraphStyle
var paragraphStyle: NSParagraphStyle? = mutableAttributedText.attribute(NSParagraphStyleAttributeName, at: 0, longestEffectiveRange: nil, in: entireRange) as? NSParagraphStyle
if paragraphStyle == nil {
// why TTTAttributedLabel :(
paragraphStyle = NSParagraphStyle()
}
// safe NSParagraphStyle
guard let safeParagraphStyle: NSParagraphStyle = paragraphStyle
else { assertionFailure() ; return }
// NSMutableParagraphStyle
guard let mutableParagraphStyle: NSMutableParagraphStyle = safeParagraphStyle.mutableCopy() as? NSMutableParagraphStyle
else { assertionFailure() ; return }
// this is where the magic happens
mutableParagraphStyle.lineSpacing = lineSpacing
mutableAttributedText.addAttribute(NSParagraphStyleAttributeName, value: mutableParagraphStyle, range: entireRange)
// assign attributed text which has all the existing attributes plus the new line spacing attribute which is inside the paragraphstyle attribute...
self.attributedText = mutableAttributedText
}
}
extension NSRange {
// Is it safe to use range on the string?
func isValidNSRange(within string: String) -> Bool {
if self.location != NSNotFound
&& self.length > 0
&& self.location + self.length - 1 < string.length
&& self.location >= 0
{
return true
} else {
return false
}
}
}
我已经研究过这个问题,在 Whosebug 上找不到答案。所以我分享我自己的 FWIW。 (我想包含 CoreText
标签,这样可以很容易地搜索到,但我的名声不允许)
解决方案
extension UIFont {
func getLineSpacing(with percentage: CGFloat = 1) -> CGFloat {
let lineSpacing: CGFloat = (self.lineHeight - self.pointSize)// /2
return lineSpacing * percentage
}
}
我基于我的解决方案 this article and this interesting Chinese article。更具体地说,我附上了我用来推断答案的部分的屏幕截图:
有没有办法将 lineSpacing
property of NSParagraphStyle
/ NSMutableParagraphStyle
attribute of an NSAttributedString
对象设置为字体 base/original lineSpacing
的百分比?
lineSpacing
是 NSParagraphStyle
的 属性 而不是 UIFont
,因此不可能知道字体的原始 lineSpacing
是什么。
作为参考,这是我写的一个小扩展,用于将 lineSpacing
分配给 UILabel
(累积,不会导致标签的 attributedString 上的信息丢失):
import UIKit
extension UILabel {
/// -important: must be called after setting the `text` property so the computed NSRange would be valid
func setLineSpacing(with lineSpacing: CGFloat) {
// get safe string
guard let textString = self.text, !textString.isEmpty
else { return }
// get the range
let entireRange: NSRange = (textString as NSString).range(of: textString)
guard entireRange.isValidNSRange(within: textString)
else { assertionFailure() ; return }
// NSMutableAttributedText
guard let mutableAttributedText: NSMutableAttributedString = self.attributedText?.mutableCopy() as? NSMutableAttributedString
else { assertionFailure() ; return }
// NSParagraphStyle
var paragraphStyle: NSParagraphStyle? = mutableAttributedText.attribute(NSParagraphStyleAttributeName, at: 0, longestEffectiveRange: nil, in: entireRange) as? NSParagraphStyle
if paragraphStyle == nil {
// why TTTAttributedLabel :(
paragraphStyle = NSParagraphStyle()
}
// safe NSParagraphStyle
guard let safeParagraphStyle: NSParagraphStyle = paragraphStyle
else { assertionFailure() ; return }
// NSMutableParagraphStyle
guard let mutableParagraphStyle: NSMutableParagraphStyle = safeParagraphStyle.mutableCopy() as? NSMutableParagraphStyle
else { assertionFailure() ; return }
// this is where the magic happens
mutableParagraphStyle.lineSpacing = lineSpacing
mutableAttributedText.addAttribute(NSParagraphStyleAttributeName, value: mutableParagraphStyle, range: entireRange)
// assign attributed text which has all the existing attributes plus the new line spacing attribute which is inside the paragraphstyle attribute...
self.attributedText = mutableAttributedText
}
}
extension NSRange {
// Is it safe to use range on the string?
func isValidNSRange(within string: String) -> Bool {
if self.location != NSNotFound
&& self.length > 0
&& self.location + self.length - 1 < string.length
&& self.location >= 0
{
return true
} else {
return false
}
}
}
我已经研究过这个问题,在 Whosebug 上找不到答案。所以我分享我自己的 FWIW。 (我想包含 CoreText
标签,这样可以很容易地搜索到,但我的名声不允许)
解决方案
extension UIFont {
func getLineSpacing(with percentage: CGFloat = 1) -> CGFloat {
let lineSpacing: CGFloat = (self.lineHeight - self.pointSize)// /2
return lineSpacing * percentage
}
}
我基于我的解决方案 this article and this interesting Chinese article。更具体地说,我附上了我用来推断答案的部分的屏幕截图: