Как отформатировать числа, поступающие с конечной точки в моем представлении SwiftUI?

#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 спасибо и хорошего улова. Да, я обновил группу захвата в регулярном выражении, чтобы исключить звездочки.