Я получил задание получить текст из облачной базы данных и преобразовать его в текстовое представление
правила следующие: каждое слово, которое начинается с $ и заканчивается на $, должно быть выделено жирным шрифтом:
let str = "$random$"
let extractStr = "random"
Text(extractStr).bold()
каждое слово, которое начинается с ~ и заканчивается на ~, должно быть активным
let str = "~random~"
let extractStr = "random"
Text(extractStr).onTapGesture { print("tapping")}
каждое слово, которое начинается с% и заканчивается на%, должно быть красным
let str = "%random%"
let extractStr = "random"
Text(extractStr).foregroundColor(Color.red)
и так далее. различные виды правил.
общая цель - объединить весь текст в один абзац.
Это возможно при суммировании представлений текстов без каких-либо жестов, но когда я пытаюсь суммировать текстовое представление жестом касания все разваливается
например, я создал длинный текст
let text1 = "$Hello$ my dear fellows. I want to provide #you# this
%awesome% long Text. I shall $talk$ a bit more to show
@you@ that when the text is $very very long$ , $it
doesn’t behave as I wanted to$. \n\n Lets #investigate a
bit more# and see how this text can behave. \n\n ~you can
click me~ and ~you can click me also~ and if you need
to, you have ~another clickable text~"
, и мой желаемый результат таков:
Вот что я пробовал
Я преобразовал его в массив:
let array1 = [$Hello$, my, dear, fellows., I, want, to, provide,
#you#, this, %awesome, long, text. ......]
после этого я провел некоторую проверку и создал массив текстов :
var arrayOfText: [Text] = []
Я сделал несколько лог c и в итоге получил следующее:
arrayOfText = [Text("Hello").bold(), Text("my"),
Text("dear").underline(),
Text("fellows."), Text("I"), Text("want"), Text("to")
Text("provide"), Text("you").foregroundColor(.blue),
Text("this"), Text("awesome").foregroundColor(.red),
Text("long"), Text("text"), ... ... ...
Text("another clickable text").onTapGesture{print("tap")}] // <-- Text with tap gesture, this is not valid...
Теперь я могу oop просмотреть тексты и просуммировать их все:
var newText: Text = Text("")
for text in arrayOfText {
newText = newText + text
}
но это не удается ... Я не могу назначить текст с жестом касания в массив текста
Я получил эту ошибку:
Could not cast value of type 'SwiftUI.ModifiedContent<SwiftUI.Text, SwiftUI.AddGestureModifier<SwiftUI._EndedGesture<SwiftUI.TapGesture>>>' (0x7fc8c08e9758) to 'SwiftUI.Text' (0x7fff8166cd30).
Итак, я попытался сделать несколько обходной путь и установите массив как массив AnyView
var arrayOfText: [AnyView] = []
, но затем, когда я передаю текст в AnyView
, я получаю эту ошибку:
Cast from 'AnyView' to unrelated type 'Text' always fails
любые идеи, как я могу это осуществить?
ОБНОВЛЕНИЕ
Я пробовал использовать метод Аспери:
struct StringPresenter: View {
let text1 = "hello $world$ I am %a% &new&\n\n~robot~"
var body: some View {
ForEach(text1.split(separator: "\n"), id: \.self) { line in
HStack(spacing: 4) {
ForEach(line.split(separator: " "), id: \.self) { part in
self.generateBlock(for: part)
}
}
}
}
private func generateBlock(for str: Substring) -> some View {
Group {
if str.starts(with: "$") {
Text(str.dropFirst().dropLast(1))
.bold()
} else
if str.starts(with: "&") {
Text(str.dropFirst().dropLast(1))
.font(Font.body.smallCaps())
} else
if str.starts(with: "%") {
Text(str.dropFirst().dropLast(1))
.italic().foregroundColor(.red)
} else
if str.starts(with: "~") {
Text(str.dropFirst().dropLast(1))
.underline().foregroundColor(.blue).onTapGesture { print("tapping ")}
}
else {
Text(str)
}
}
}
}
Но это не работает с длинным текстом. все просмотры сворачиваются друг на друга
Вот как это выглядит Пример:
