Создание рекурсивного текстового представления в SwiftUI

Моя цель - создать представление SwiftUI, которое принимает строку и автоматически форматирует этот текст в текстовые представления. Часть строки, требующая форматирования, определяется с помощью регулярного выражения, а затем возвращается как Range<String.Index>. Это можно использовать для восстановления String после применения форматирования к соответствующим текстовым представлениям. Поскольку может быть несколько экземпляров текста, которые необходимо отформатировать, запуск функции форматирования должен выполняться рекурсивно.

      struct AttributedText: View {
    @State var text: String
    
    var body: some View {
        AttributedTextView(text: text)
    }
    
    @ViewBuilder
    private func AttributedTextView(text: String) -> some View {
        if let range = text.range(of: "[0-9]+d[0-9]+", options: .regularExpression) {
       
        //The unattributed text
        Text(text[text.startIndex..<range.lowerBound]) +
            
            //Append the attributed text
            Text(text[range]).bold() +
            
            //Search for additional instances of text that needs attribution
            AttributedTextView(text: String(text[range.upperBound..<text.endIndex]))
        
        } else {
            //If the searched text is not found, add the rest of the string to the end
            Text(text)
        }
    }

Я получаю ошибку Cannot convert value of type 'some View' to expected argument type 'Text', с рекомендуемым исправлением, чтобы обновить рекурсивную строку до AttributedTextView(text: String(text[range.upperBound..<text.endIndex])) as! Text. Я применяю это исправление, но по-прежнему вижу ту же ошибку компилятора с тем же предложенным исправлением.

Несколько способов обхода, которые я пробовал:

  • Изменение типа возврата с some View к Text. Это создает другую ошибку Cannot convert value of type '_ConditionalContent<Text, Text>' to specified type 'Text'. Я особо не исследовал это дальше, так как имеет смысл, что возвращаемое значение зависит от этого условия.
  • Возврат группы, а не текста, что вызывает дополнительные ошибки во всем файле SwiftUI

Ни одно из этих решений не кажется «быстрым». Что можно сделать по-другому? Я что-то неправильно понимаю в SwiftUI?

1 ответ

Здесь нужно уточнить несколько моментов:

В + перегрузка работает только между Textsпоэтому он говорит, что не может преобразовать (ваш возвращаемый тип) в. + ==, + some View == ☠️

Изменение типа возврата на вас не работает, потому что вы используете, remove, и он будет работать нормально.

Почему? позволяет SwiftUIчтобы отложить оценку закрытия на потом, но гарантирует, что это приведет к определенному типу представления (не AnyView). В случае, если ваше закрытие возвращает либо a, либо Image это удобно, но в вашем случае, когда это всегда приводит к Textв этом нет необходимости , @ViewBuilder заставляет возвращаемый тип быть ConditionalContent<Text, Text>чтобы он мог иметь разные типы.

Вот что должно работать:

      private static func attributedTextView(text: String) -> Text {
    if let range = text.range(of: "[0-9]+d[0-9]+", options: .regularExpression) {

    //The unattributed text
    return Text(text[text.startIndex..<range.lowerBound]) +

        //Append the attributed text
        Text(text[range]).bold() +

        //Search for additional instances of text that needs attribution
        AttributedTextView(text: String(text[range.upperBound..<text.endIndex]))

    } else {
        //If the searched text is not found, add the rest of the string to the end
        return Text(text)
    }
}

Я тоже сделал его статическим, потому что здесь нет состояния, это чистая функция и сделал его в нижнем регистре, чтобы было ясно, что это функция, а не тип (имя функции выглядит как View тип).

Вы бы просто назвали это Self.attributedTextView(text: ...)

Другие вопросы по тегам