在 SwiftUI 中构建递归文本视图
Build Recursive Text View in SwiftUI
我的目标是创建一个 SwiftUI 视图,它接受一个字符串并自动将该文本格式化为文本视图。使用正则表达式找到需要格式化的字符串部分,然后 returned 作为 Range。一旦将格式应用于适当的文本视图,这可用于重建字符串。由于可能有多个文本实例需要格式化,运行 格式化函数应该递归完成。
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
。我应用了此修复程序,但仍然看到相同的编译器错误和相同的建议修复程序。
我尝试过的一些解决方法:
- 正在将 return 类型从
some View
更改为 Text
。这会产生一个不同的错误 Cannot convert value of type '_ConditionalContent<Text, Text>' to specified type 'Text'
。我并没有真正进一步探讨这一点,因为 return 值依赖于该条件确实有意义。
- 返回组而不是文本,这会导致整个 SwiftUI 文件出现额外错误
这些解决方案都不是很“敏捷”。解决这个问题的另一种方法是什么?我对 SwiftUI 有什么误解吗?
这里有几点需要澄清:
Text
的 +
重载仅在 Texts
之间起作用,这就是为什么它说它不能将 some View
(您的 return 类型)转换为 Text
。 Text
+ Text
== Text
, Text
+ some View
== ☠️
将 return 类型更改为 Text
对您不起作用,因为您使用的是 @ViewBuilder
,移除 @ViewBuilder
即可正常工作。
为什么? @ViewBuilder
允许 SwiftUI
推迟对闭包的评估,但确保它会产生特定的视图类型(不是 AnyView ).如果您的闭包 returns either a Text
或 Image
这很方便,但在您的情况下它总是导致 Text
不需要,@ViewBuilder
强制 return 类型为 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: ...)
我的目标是创建一个 SwiftUI 视图,它接受一个字符串并自动将该文本格式化为文本视图。使用正则表达式找到需要格式化的字符串部分,然后 returned 作为 Range
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
。我应用了此修复程序,但仍然看到相同的编译器错误和相同的建议修复程序。
我尝试过的一些解决方法:
- 正在将 return 类型从
some View
更改为Text
。这会产生一个不同的错误Cannot convert value of type '_ConditionalContent<Text, Text>' to specified type 'Text'
。我并没有真正进一步探讨这一点,因为 return 值依赖于该条件确实有意义。 - 返回组而不是文本,这会导致整个 SwiftUI 文件出现额外错误
这些解决方案都不是很“敏捷”。解决这个问题的另一种方法是什么?我对 SwiftUI 有什么误解吗?
这里有几点需要澄清:
Text
的 +
重载仅在 Texts
之间起作用,这就是为什么它说它不能将 some View
(您的 return 类型)转换为 Text
。 Text
+ Text
== Text
, Text
+ some View
== ☠️
将 return 类型更改为 Text
对您不起作用,因为您使用的是 @ViewBuilder
,移除 @ViewBuilder
即可正常工作。
为什么? @ViewBuilder
允许 SwiftUI
推迟对闭包的评估,但确保它会产生特定的视图类型(不是 AnyView ).如果您的闭包 returns either a Text
或 Image
这很方便,但在您的情况下它总是导致 Text
不需要,@ViewBuilder
强制 return 类型为 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: ...)