0

我的目标是创建一个 SwiftUI 视图,它接受一个字符串并将该文本自动格式化为文本视图。使用正则表达式找到需要格式化的字符串部分,然后作为 Range<String.Index> 返回。一旦将格式应用于适当的文本视图,这可用于重建字符串。由于可能有多个文本实例需要格式化,因此应该递归地运行格式化函数。

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 ViewText。这会产生不同的错误Cannot convert value of type '_ConditionalContent<Text, Text>' to specified type 'Text'。我并没有真正进一步探索这一点,因为返回值依赖于该条件是有道理的。
  • 返回一个组而不是一个文本,这会导致整个 SwiftUI 文件出现额外的错误

这些解决方案都不是很“Swifty”。还有什么方法可以解决这个问题?我是否误解了 SwiftUI 中的某些内容?

4

1 回答 1

1

这里有几点需要澄清:

only的+重载在这Text之间起作用,Texts这就是为什么它说它不能将some View(您的返回类型)转换为Text. Text+ Text== Text, Text+ some View==☠️

将返回类型更改为Text对您不起作用,因为您正在使用@ViewBuilder,删除@ViewBuilder它会正常工作。

为什么? @ViewBuilder允许SwiftUI推迟对闭包的评估,但确保它会导致特定的视图类型(不是 AnyView)。如果您的闭包返回aTextanImage这很方便,但在您总是导致不需要Text的情况下,强制返回类型使其可以具有不同的类型。@ViewBuilderConditionalContent<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: ...)

于 2021-04-20T10:02:40.727 回答