Как разделить NSAttributedString между представлениями с одинаковыми границами с правильной переносом слов - PullRequest
0 голосов
/ 08 июля 2019

Я уже давно борюсь с этим. Существуют API, которые дают нам размер границ для заданных атрибутов NSAttributedString.

Но не существует прямого способа получить диапазон строк, который бы соответствовал заданным границам.

Мое требование - разместить очень длинную строку в нескольких постраничных представлениях (PDF не вариант и не прокрутка). Следовательно, я должен определить размер строки для каждого представления (те же границы).

После исследования я обнаружил, что CTFramesetterSuggestFrameSizeWithConstraints и его друзья в Core Text могут помочь. Я попробовал подход , описанный здесь , но у получающихся диапазонов есть одна неприятная проблема:

Он игнорирует разрывы слов (другая проблема, не связанная с Базовым текстом, но мне бы очень хотелось посмотреть, есть ли какое-то решение и для этого).

Как правило, я хочу разбить текст на несколько UITextView объектов, но не получить правильные атрибуты разделения строк.

Примечание: Мои NSAttributedString атрибуты следующие:

let attributes: [NSAttributedString.Key : Any] = [.foregroundColor : textColor, .font : font, .paragraphStyle : titleParagraphStyle]

(titleParagraphStyle имеет lineBreakMode, установленный на byWordWrapping)

extension UITextView
{
    func getStringSplits (fullString: String, attributes: [NSAttributedString.Key:Any]) -> [String]
    {
        let attributeString = NSAttributedString(string: fullString, attributes: attributes)
        let frameSetterRef = CTFramesetterCreateWithAttributedString(attributeString as CFAttributedString)

        var initFitRange:CFRange = CFRangeMake(0, 0)
        var finalRange:CFRange = CFRangeMake(0, fullString.count)

        var ranges: [Int] = []
        repeat
        {   
          CTFramesetterSuggestFrameSizeWithConstraints(frameSetterRef, initFitRange, attributes as CFDictionary, CGSize(width: bounds.size.width, height: bounds.size.height), &finalRange)
            initFitRange.location += finalRange.length
            ranges.append(finalRange.length)
        }
        while (finalRange.location < attributeString.string.count)

        var stringSplits: [String] = []

        var startIndex: String.Index = fullString.startIndex

        for n in ranges
        {
            let endIndex = fullString.index(startIndex, offsetBy: n, limitedBy: fullString.endIndex) ?? fullString.endIndex
            let theSubString = fullString[startIndex..<endIndex]
            stringSplits.append(String(theSubString))
            startIndex = endIndex
        }

        return stringSplits
    }
}

1 Ответ

1 голос
/ 08 июля 2019

Мое требование - разместить очень длинную строку в нескольких постраничных представлениях (PDF не вариант, а также прокрутка).Следовательно, я должен определить размер строки для каждого представления (те же границы).

Нет, вам не нужно это выяснять.Стек текстового набора сделает это за вас.

Фактически, UITextView будет передавать длинный текст из одного текстового представления в другое автоматически .Это всего лишь вопрос настройки стека текстового набора - один менеджер компоновки с несколькими текстовыми контейнерами.

...