1

我正在尝试添加一个支持部分(这是一个变成更多内容的演示),并认为我可以获取一个 json 文件并将其添加到 DisclosureGroup 给最终用户。

本来以为是网络问题,但是在本地添加文件还是出现了同样的问题。

当我在模拟器中运行它并尝试打开其中一个 DisclosureGroup 项目时,它没有打开。如果我按下更多的 RAM 使用量会增加,但看不到它应该在初始 Bundle 加载到数组之后的原因。

这是我正在测试的数据:

SupportQuestions.json

{
 "sections": [
  {
   "title": "Section title 1",
   "description": null,
   "questions": [
    {
     "title": "Question title 1",
     "response": "Answer 1"
    },
    {
     "title": "Question title 3",
     "response": "Answer 3"
    }
   ]
  },
  {
   "title": "Section title 2",
   "description": "Section description",
   "questions": [
    {
     "title": "Question title 4",
     "response": "Answer 4"
    },
    {
     "title": "Question title 5",
     "response": "Answer 5"
    },
    {
     "title": "Question title 6",
     "response": "Answer 6"
    }
   ]
  },
  {
   "title": "Section title 3",
   "description": "Another section description",
   "questions": [
    {
     "title": "Question title 7",
     "response": "Answer 7"
    },
    {
     "title": "Question title 8",
     "response": "Answer 8"
    },
    {
     "title": "Question title 9",
     "response": "Answer 9"
    }
   ]
  }
 ]
}

然后是我在视图中使用的 Swift:

struct SettingsHelpView: View {

  @State private
  var suppportItems: [SupportSections.SupportCategory] = []
  var body: some View {
    Form {
      ForEach(suppportItems) {
        item in
          Section {
            ForEach(item.questions) {
              question in
                DisclosureGroup {
                  Text(question.response)
                }
              label: {
                Text(question.title).bold()
              }
            }
          }
        header: {
          Text(item.title)
        }
        footer: {
          Text(item.decription ?? "")
        }
      }
    }
    .onAppear {
      fetchHelpSection()
    }
  }

  private func fetchHelpSection() {
    let questions = Bundle.main.decode(SupportSections.self, from: "SupportQuestions.json")
    suppportItems = questions.sections
  }
}

模型

struct SupportSections: Decodable {
 let sections: [SupportCategory]

 struct SupportCategory: Decodable, Identifiable {
  var id: String { UUID().uuidString }
  let title: String
  let decription: String?
  let questions: [SupportQuestion]

  struct SupportQuestion: Decodable, Identifiable {
   var id: String { UUID().uuidString }
   let title: String
   let response: String
  }
 }
}

捆绑+分机

extension Bundle {
 func decode<T: Decodable>(_ type: T.Type, from file: String, dateDecodingStategy: JSONDecoder.DateDecodingStrategy = .deferredToDate, keyDecodingStrategy: JSONDecoder.KeyDecodingStrategy = .useDefaultKeys) -> T {

  guard let url = self.url(forResource: file, withExtension: nil) else {
   fatalError("Error: Failed to locate \(file) in bundle.")
  }
  guard let data = try? Data(contentsOf: url) else {
   fatalError("Error: Failed to load \(file) from bundle.")
  }
  let decoder = JSONDecoder()
  decoder.dateDecodingStrategy = dateDecodingStategy
  decoder.keyDecodingStrategy = keyDecodingStrategy
  guard let loaded = try? decoder.decode(T.self, from: data) else {
   fatalError("Error: Failed to decode \(file) from bundle.")
  }
  return loaded
 }
}

正在发生的视频(抱歉不知道如何调整大小):

伊姆古尔

4

1 回答 1

0

问题来自id模型中的属性。现在,您已id定义为计算属性:

var id: String { UUID().uuidString }

这意味着每次 SwiftUI 请求一个 时id,它都会得到一个不同的值,因为UUID每次都会生成一个新值。这让 SwiftUI 感到困惑,它“关闭”了,DisclosureGroup因为它认为它是新的View(因为新的 ID)。

要解决此问题,请将您的id属性声明为非计算值并提供CodingKeys,以便系统不会尝试从JSON文件中解码该属性。

struct SupportSections: Decodable {
    let sections: [SupportCategory]
    
    struct SupportCategory: Decodable, Identifiable {
        var id = UUID().uuidString //<-- Here
        let title: String
        let description: String? //note that you had a typo here in your original code
        let questions: [SupportQuestion]
        
        enum CodingKeys : String, CodingKey {
            case title, description, questions
        }
        
        struct SupportQuestion: Decodable, Identifiable {
            var id: String = UUID().uuidString //<-- Here
            let title: String
            let response: String
            
            enum CodingKeys : String, CodingKey {
                case title, response
            }
        }
    }
}
于 2022-01-30T06:07:41.663 回答