SwiftUI:在同一行上组合文本

SwiftUI: Combining Text on the same line

我正在编写的 SwiftUI 应用程序有大块文本,所以我正在尝试创建一种“标记语言”,我可以在我的 JSON 文件中使用它来保存文本,以定义何时单词应该加粗。问题是,我似乎无法阻止新的文本块转到不同的行。

这是我目前拥有的相关代码。

struct formattedText: View {
var text: String

var body: some View {
    let split = text.components(separatedBy: "**")
    Group {
        ForEach(split, id: \.self) { line in
            if line.hasPrefix("$$") {
                Text(line.trimmingCharacters(in: CharacterSet(charactersIn: "$")))
                    .bold()
            } else {
                Text(line)
            }
        }
    }
    .lineLimit(nil)
    .multilineTextAlignment(.leading)
}

使用这段代码,我可以在单词前加上 **$$,在单词后加上 **,将其定义为粗体。

唯一的问题是每次我加粗一个词时它都会换行。我知道解决这个问题的传统方法是:

Text("Simple ") + Text("Swift ") + Text("Guide")

但这不适用于我的 ForEach 循环。有什么建议吗?

ForEach 创建单独的视图。你真的只想要一个文本,所以你的意思是 for...in 循环:

var body: some View {
    let split = text.components(separatedBy: "**")
    var result = Text("")
    for line in split {
        if line.hasPrefix("$$") {
            result = result + Text(line.trimmingCharacters(in: CharacterSet(charactersIn: "$")))
                .bold()
        } else {
            result = result + Text(line)
        }
    }

    return result
        .lineLimit(nil)
        .multilineTextAlignment(.leading)
}

由于您可能想要的不仅仅是粗体,所以您可能会发现将该部分提取到它自己的函数或函数集合中很有用:

private func applyAttributes(line: String) -> Text {
    if line.hasPrefix("$$") {
        return Text(line.trimmingCharacters(in: CharacterSet(charactersIn: "$")))
            .bold()
    } else {
        return Text(line)
    }
}

有了这个,构建这个就更简单了:

var body: some View {
    text.components(separatedBy: "**")
        .map(applyAttributes)
        .reduce(Text(""), +)
        .lineLimit(nil)
        .multilineTextAlignment(.leading)
}