在 ForEach 内部循环时 DisclosureGroup 未打开
DisclosureGroup not opening when looped inside ForEach
我正在尝试添加一个支持部分(这是一个变成更多内容的演示)并认为我可以获取一个 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
}
}
正在发生的事情的视频(抱歉不知道如何调整大小):
问题出在模型中的 id
属性。现在,您将 id
定义为计算的 属性:
var id: String { UUID().uuidString }
这意味着每次 SwiftUI 请求 id
时,它都会得到一个 不同的 值,因为每次都会生成一个新的 UUID
。这让 SwiftUI 感到困惑,它 'closes' 和 DisclosureGroup
因为它认为它是一个新的 View
(因为新 ID)。
要解决此问题,请将您的 id
属性声明为 non-computed 值并提供 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
}
}
}
}
我正在尝试添加一个支持部分(这是一个变成更多内容的演示)并认为我可以获取一个 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
}
}
正在发生的事情的视频(抱歉不知道如何调整大小):
问题出在模型中的 id
属性。现在,您将 id
定义为计算的 属性:
var id: String { UUID().uuidString }
这意味着每次 SwiftUI 请求 id
时,它都会得到一个 不同的 值,因为每次都会生成一个新的 UUID
。这让 SwiftUI 感到困惑,它 'closes' 和 DisclosureGroup
因为它认为它是一个新的 View
(因为新 ID)。
要解决此问题,请将您的 id
属性声明为 non-computed 值并提供 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
}
}
}
}