Как получить lineSpacing из UIFont? (для расчета процентного значения) - PullRequest
0 голосов
/ 14 января 2019

Есть ли способ установить lineSpacing свойство NSParagraphStyle / NSMutableParagraphStyle атрибута NSAttributedString указывать в процентах от базы шрифта / оригинала lineSpacing?

lineSpacing является свойством NSParagraphStyle, а не UIFont, поэтому невозможно узнать, каков исходный lineSpacing для шрифта.

В качестве справки, вот небольшое расширение, которое я написал для присвоения lineSpacing UILabel (накопительное, не вызывает потери информации в атрибуте String):

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
        }
    }
}

Я уже исследовал проблему, не нашел ответа на Stackoverflow. Так что я делюсь своим собственным FWIW . (Я хотел включить тег CoreText, чтобы его можно было легко найти, но моя репутация не позволяет мне)

1 Ответ

0 голосов
/ 14 января 2019

Решение

extension UIFont {
    func getLineSpacing(with percentage: CGFloat = 1) -> CGFloat {
        let lineSpacing: CGFloat = (self.lineHeight - self.pointSize)// /2

        return lineSpacing * percentage
    }
}

Я основал свое решение эта статья и эта интересная китайская статья . Более конкретно, я прилагаю скриншоты частей, которые я использовал для вывода ответа:

https://belka.us/en/uilabel-line-height-in-swift/

https://www.jianshu.com/p/50b3d434cbc0

...