Как получить диапазон первой строки в строке? - PullRequest
0 голосов
/ 22 февраля 2019

Я бы хотел изменить форматирование первой строки текста в NSTextView (укажите другой размер и вес шрифта, чтобы он выглядел как заголовок).Поэтому мне нужен диапазон первой строки.Один из способов - это:

guard let firstLineString = textView.string.components(separatedBy: .newlines).first else {
    return
}
let range = NSRange(location: 0, length: firstLineString.count)

Однако я мог бы работать с довольно длинными текстами, поэтому кажется неэффективным сначала разбивать строку всю на строчные компоненты, когда все янужен компонент первой строки.Таким образом, имеет смысл использовать метод firstIndex(where:):

let firstNewLineIndex = textView.string.firstIndex { character -> Bool in
    return CharacterSet.newlines.contains(character)
}
// Then: Create an NSRange from 0 up to firstNewLineIndex. 

Это не работает, и я получаю ошибку:

Невозможно преобразовать значение типа '(Unicode.Scalar) -> Bool 'к ожидаемому типу аргумента' Character '

, поскольку метод contains принимает не Character, а Unicode.Scalar в качестве параметра (что на самом деле не имеет смысладля меня, потому что тогда он должен называться UnicodeScalarSet, а не CharacterSet, но не имеет значения ...).

Мой вопрос:

Как я могу реализовать это в эффективномкстати, без предварительной нарезки всей строки?

(необязательно использовать метод firstIndex(where:), но, похоже, это путь.)

Ответы [ 2 ]

0 голосов
/ 22 февраля 2019

A String.Index диапазон для первой строки в string может быть получен с помощью

let range = string.lineRange(for: ..<string.startIndex)

Если вам нужно это как NSRange, тогда

let nsRange = NSRange(range, in: string)

делаетобмануть.

0 голосов
/ 22 февраля 2019

Вы можете использовать rangeOfCharacter, который возвращает Range<String.Index> первого символа из набора в вашей строке:

extension StringProtocol where Index == String.Index {
    var partialRangeOfFirstLine: PartialRangeUpTo<String.Index> {
        return ..<(rangeOfCharacter(from: .newlines)?.lowerBound ?? endIndex)
    }
    var rangeOfFirstLine: Range<Index> {
        return startIndex..<partialRangeOfFirstLine.upperBound
    }
    var firstLine: SubSequence {
        return self[partialRangeOfFirstLine]
    }
}

Вы можете использовать его так:

var str = """
    some string 
    with new lines
"""
var attributedString = NSMutableAttributedString(string: str)
let firstLine = NSAttributedString(string: String(str.firstLine))
// change firstLine as you wish

let range = NSRange(str.rangeOfFirstLine, in: str)
attributedString.replaceCharacters(in: range, with: firstLine)
...