#swift #swiftui
Вопрос:
Я получаю данные со своей конечной точки в этом формате json:
[ { "id": 1, "chapter_content_combined": "*1* No princípio Deus criou os céus e a terra. *2* Era a terra sem forma e vazia; trevas cobriam a face do abismo, e o Espírito de Deus se movia sobre a face das águas. *3* Disse Deus: "Haja luz", e houve luz. *4* Deus viu que a luz era boa, e separou a luz das trevas....", "chapter": 1, "verses_amount": 31, "book": 1 }, { "id": 2, "chapter_content_combined": "*1* Assim foram concluídos os céus e a terra, e tudo o que neles há. *2* No sétimo dia Deus já havia concluído a obra que realizara, e nesse dia descansou. *3* Abençoou Deus o sétimo dia e o santificou, porque nele descansou de toda a obra que realizara na criação....", "chapter": 2, "verses_amount": 25, "book": 1 }, ]
А потом я просто вывожу это в своем представлении вот так:
List { ForEach(self.viewModel.chapters) { chapter in Text(chapter.chapter_content_combined) } }
Вывод на холсте выглядит следующим образом:
Как я могу отформатировать **
части из JSON (все числа и т. *1*, *2*, *3*
Д.), Чтобы они были надписаны (и окрашены), примерно так:
(notice the orange, tiny superscript numbers):
Я предполагаю, что для этого мне придется подключиться к UIKit, не зная, как поступить
Мне удалось использовать регулярное выражение для фильтрации **
деталей, но я не уверен, как с этим поступить или есть ли лучший подход
if let regex = try? NSRegularExpression(pattern: "\*([^\*]*)\*", options: .caseInsensitive) { let modChapter = regex.stringByReplacingMatches(in: chapter, options: [], range: NSRange(location: 0, length: chapter.count), withTemplate: "") // not sure what to do with this though print(modChapter) }
Комментарии:
1. Посмотрите на приписываемые строки и уценку
2. Следовало бы указать, что он мне нужен для версий, более ранних, чем iOS 15.
Ответ №1:
Следующий код использует группы захвата регулярных выражений для определения расположения элементов верхнего индекса, а затем преобразует их в объединенные Text
объекты SwiftUI:
struct Chapter : Decodable, Identifiable { var id : Int var chapter_content_combined : String } let chapters : [Chapter] = [.init(id: 0, chapter_content_combined: "*1* No princípio Deus criou os céus e a terra. *2* Era a terra sem forma e vazia; trevas cobriam a face do abismo, e o Espírito de Deus se movia sobre a face das águas. *3* Disse Deus: "Haja luz", e houve luz. *4* Deus viu que a luz era boa, e separou a luz das trevas...."),.init(id: 1, chapter_content_combined: "*1* Assim foram concluídos os céus e a terra, e tudo o que neles há. *2* No sétimo dia Deus já havia concluído a obra que realizara, e nesse dia descansou. *3* Abençoou Deus o sétimo dia e o santificou, porque nele descansou de toda a obra que realizara na criação....")] enum TextType { case superscript(String) case normal(String) } func transformInput(input : String) -> [TextType] { var results : [TextType] = [] let range = NSRange(location: 0, length: input.utf16.count) let regex = try! NSRegularExpression(pattern: "\*(\d )\*([^\*]*)") regex.matches(in: input, options: [], range: range).forEach { match in guard let superscriptRange = Range(match.range(at: 1), in: input), let contentRange = Range(match.range(at: 2), in: input) else { return } results.append(.superscript(String(input[superscriptRange]))) results.append(.normal(String(input[contentRange]))) } return results } struct ContentView : View { @ViewBuilder func formattedText(input : String) -> some View { let segments = transformInput(input: input).map { textType -> Text in switch textType { case .superscript(let str): return Text(str) .font(.system(size: 10.0)) .baselineOffset(6.0) .foregroundColor(.red) case .normal(let str): return Text(str) } } VStack { segments.reduce(Text(""), { $0 $1 }) } } var body: some View { ForEach(chapters) { chapter in formattedText(input: chapter.chapter_content_combined) } } }
Что приводит к:
Обратите внимание, что вам, возможно, придется отредактировать предложение «защита» в случае, если существуют сценарии форматирования с группами захвата, не встречающимися в вашем примере ввода.
Комментарии:
1. У вас была возможность опробовать этот ответ? Это сработало для вас?
2. Почему такой низкий голос? Я рад удалить это, если это не было полезно, но, похоже, это действительно решает вашу проблему. Я вижу, что вы задаете новые вопросы, поэтому я немного смущен, почему это вообще не требовало ответа.
3. Хороший ответ (проголосовали)! Все же есть какой-нибудь способ избавиться от звездочек?
4. @aheze спасибо и хорошего улова. Да, я обновил группу захвата в регулярном выражении, чтобы исключить звездочки.