Я пытался следовать учебнику по CoreText и тому, как рисовать текст, и я реализовал эту функцию в своем customView.
override func draw(_ rect: CGRect) {
guard let context = UIGraphicsGetCurrentContext() else { return }
let path = CGMutablePath()
path.addRect(bounds)
let attrString = NSAttributedString(string: "Hello World")
let framesetter = CTFramesetterCreateWithAttributedString(attrString as CFAttributedString)
let frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, attrString.length), path, nil)
CTFrameDraw(frame, context)
}
Он отлично работает, когда текст короткий, но когда текст становится более 10 тысяч букв, он отображается неправильно. Есть ли какое-нибудь решение для этого?
ПРИМЕЧАНИЕ: это происходит, когда текст на арабском, а не на английском.
Вот рендер, когда текст маленький:
Вот рендеринг текста, когда количество текста превышает 10 КБ, он кажется разрозненным и перевернутым:
Привет @RobNapier, Большое спасибо за ваш повтор. Как вы рекомендовали, я отправил проблему в DTS, и они ответили следующее: в конкретном образце, который вы предоставили, на самом деле может быть не столько размер текста, сколько размер. одно английское слово в середине текста, которое может потребовать дополнительной обработки Unicode. Но по умолчанию те части CoreText, которые отображают сложный Unicode, по умолчанию отключены, чтобы избежать снижения производительности и других потенциальных проблем. Это контролируется параметром набора текста kCTTypesetterOptionAllowUnboundedLayout (по умолчанию false).
@RobNapier, Итак, как я могу включить такое значение, и, как вы знаете, я не использовал класс Typesetter?
Я воспроизвел эту проблему, используя текст с сайта istizada.com/arabic-lorem-ipsum (неоднократно копируя абзац). У него определенно не должно быть смешанного двунаправленного текста (ltr и rtl). И это определенно происходит, когда я пересекаю определенный размер, поэтому я не верю их теории «одного английского слова». Но kCTTypesetterOptionAllowUnboundedLayout, кажется, исправляет это. Я собрал свой тестовый пример, и он не имеет правильного макета, но я напишу правильный пример позже сегодня утром. (Обратите внимание, что я думаю, что использование attrString.draw(in: rect)
вместо основного текста здесь будет работать, но я понимаю, что вы хотите изучить CT)
Да, я тоже не согласен с ними по поводу этой строки «одно английское слово», большое спасибо @RobNapier
Основываясь на ваших отзывах от Apple, кажется, что CTFramesetter отключает расширенную компоновку, когда длина строки превышает определенный размер. (Их предположение, что это из-за того, что текст смешанного направления звучит неправильно; я определенно воспроизвел это только на арабском языке.)
Чтобы исправить это, вам нужно создать фреймсеттер с пользовательским наборщиком, который всегда выполняет расширенную компоновку (kCTTypesetterOptionAllowUnboundedLayout). К счастью, это просто.
Сначала создайте собственный верстальщик, а затем используйте его для создания фреймсеттера:
let typesetterOptions = [kCTTypesetterOptionAllowUnboundedLayout: true] as CFDictionary
let typesetter = CTTypesetterCreateWithAttributedStringAndOptions(attrString,
typesetterOptions)!
let framesetter = CTFramesetterCreateWithTypesetter(typesetter)
Это ошибка. Я воспроизвел это так, как вы описываете, где-то около 10 тысяч букв. Я вижу ту же проблему, если вы пропустите CTFrameSetter и будете использовать CTLine и CTTypesetter напрямую. Кроме «сделайте свои строки короче», я не уверен, что здесь делать, кроме как поговорить с Apple. Я бы, наверное, использовал для этого DTS, если он у вас остался в этом году. (нажмите «Поддержка на уровне кода» на панели учетной записи на сайте developer.apple.com) Это действительно интересная ошибка.