Почему при использовании TextKit для рендеринга текста вторая строка оказывается короче первой?

Пример проекта: http://d.pr/f/1coXu

Я использую TextKit для рендеринга текста в то, что по сути является очень простым воссозданием UILabel. Код очень прост и в этом примере просто рисует NSAttributedString в самом представлении:

class TextKitView: UIView {
    // TextKit Objects
    var textStorage: NSTextStorage!
    var textContainer: NSTextContainer!
    var layoutManager: NSLayoutManager!

    override init(frame: CGRect) {
        super.init(frame: frame)

        backgroundColor = UIColor.clearColor()

        layoutManager = NSLayoutManager()

        textStorage = NSTextStorage(attributedString: createAttributedString())
        textStorage.addLayoutManager(layoutManager)

        textContainer = NSTextContainer(size: CGSize(width: bounds.width, height: bounds.height))
        layoutManager.addTextContainer(textContainer)
    }

    required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") }

    override func drawRect(rect: CGRect) {
        let glyphRange = layoutManager.glyphRangeForTextContainer(textContainer)
        layoutManager.drawBackgroundForGlyphRange(glyphRange, atPoint: bounds.origin)
        layoutManager.drawGlyphsForGlyphRange(glyphRange, atPoint: bounds.origin)
    }

    private func createAttributedString() -> NSAttributedString {
        let attributedString = NSMutableAttributedString(string: "Test string for testing", attributes: [NSForegroundColorAttributeName: UIColor.blackColor(), NSFontAttributeName: UIFont.systemFontOfSize(16.0)])

        let labelAttributedString = NSAttributedString(string: "Foo bar\n testing", attributes: [NSForegroundColorAttributeName: UIColor.darkGrayColor(), NSBackgroundColorAttributeName: UIColor(white: 0.95, alpha: 1.0)])
        attributedString.appendAttributedString(labelAttributedString)

        return attributedString
    }
}

Однако, когда я создаю представление:

override func viewDidLoad() {
    super.viewDidLoad()

    let textKitView = TextKitView(frame: CGRect(x: 0.0, y: 100.0, width: 320.0, height: 320.0))
    view.addSubview(textKitView)
}

В итоге это выглядит так:

введите здесь описание изображения

Где вы можете видеть, что по какой-то необъяснимой причине цвет фона и высота второй строки значительно короче, чем у первой, что выглядит очень странно.

Как предотвратить это? Что вызывает это? Если я использую UILabel и предоставляю одну и ту же атрибутированную строку, обе строки имеют одинаковую высоту. Я прикрепил очень минимальный пример проекта выше, если это поможет.


person Doug Smith    schedule 01.07.2016    source источник
comment
Я не понимаю вопроса. Тестирование Foo bar одинакового размера. Высота цвета фона в первой строке обусловлена ​​тем, что строка также содержит текст большего размера, поэтому ее высота больше; чтобы доказать это, удалите тестовую строку для тестовой части. Или обратите внимание, как нижняя часть цвета фона первой строки идеально совпадает с выносным элементом g в тестовой строке для тестирования.   -  person matt    schedule 01.07.2016
comment
@matt Хорошо, тогда, по-другому, как мне сделать высоту постоянной независимо от содержимого строки?   -  person Doug Smith    schedule 01.07.2016
comment
С кодом относительно высокого уровня (по сравнению с недрами TextKit) ваш единственный выход может состоять в том, чтобы убедиться, что каждая строка включает пробелы необходимого большего размера шрифта.   -  person Feldur    schedule 01.07.2016


Ответы (1)


Ознакомьтесь с NSParagraphStyle: https://developer.apple.com/reference/uikit/nsparagraphstyle

В этом классе есть свойства высоты строки, то есть minimumLineHeight и maximumLineHeight, которые могут выполнить то, что вы пытаетесь сделать. Вы можете установить стиль абзаца для NSAttributedString следующим образом:

let paraStyle = NSMutableParagraphStyle()
paraStyle.setParagraphStyle = NSParagraphStyle.default
paraStyle.minimumLineHeight = 50 // for example
attributedString.addAttribute(NSParagraphStyleName, value: paraStyle, range:NSMakeRange(0, attributedString.length))
person Dave Weston    schedule 15.01.2017