Я хочу создать пользовательский подкласс UILabel, который будет знать текущее количество отображаемых строк. Как я понял, UILabel автоматически меняет свое свойство attributedText
при изменении text
или font
. Поэтому я пытаюсь сделать что-то подобное:
label.text = "some very long text"
label.font = .systemFont(ofSize: 12)
guard let attrStr = label.attributedText else {
return
}
print(attrStr.lines(fittingWidth: 600).count)
...
extension NSAttributedString {
func lines(fittingWidth width: CGFloat) -> [String] {
let attributedString = self
let framesetter =
CTFramesetterCreateWithAttributedString(
attributedString
)
let path = CGPath(rect: CGRect(
x: 0,
y: 0,
width: width,
height: .greatestFiniteMagnitude
), transform: nil)
let frame = CTFramesetterCreateFrame(
framesetter,
CFRange(location: 0, length: 0),
path,
nil
)
let lines = CTFrameGetLines(frame) as! [CTLine]
var strLines = [String]()
let nsString = attributedString.string as NSString
for line in lines {
let lineRange = CTLineGetStringRange(line)
let range = NSMakeRange(lineRange.location, lineRange.length)
strLines.append(nsString.substring(with: range))
}
return strLines
}
}
Но проблема в том, что lines(fittingWidth:)
всегда возвращает только 1 строку для любой ширины подгонки, когда я использую значение attributedText
метки. В то же время, когда я сам создаю NSAttributedString
(используя свойства text
и font
), lines(fittingWidth:)
возвращает правильное количество строк. Что не так со встроенным значением attributedText
?