[英]SwiftUI app crashes when trying to expand/collapse sections on a sheet
[英]SwiftUI (2.0) list with children crashes when trying to delete the last element
我有以下代碼用於帶有孩子的 SwiftUI 列表,改編自另一個 StackOverflow 答案:
SwiftUI 2.0 帶孩子的列表 - 如何使披露按鈕的可點擊區域覆蓋整個列表項
struct ContentView: View {
@EnvironmentObject var goodies: GlobalGoodies
func listItem(for item: User) -> some View {
Text(item.name)
}
var body: some View {
NavigationView {
List {
ForEach(Array(goodies.users.enumerated()), id: \.1.id) { i, group in
DisclosureGroup(isExpanded: $goodies.users[i].isExpanded) {
ForEach(group.children ?? []) { item in
listItem(for:item)
}
.opacity(goodies.users[i].opacity)
} label: {
listItem(for: group)
.contentShape(Rectangle())
.onTapGesture {
withAnimation {
goodies.users[i].opacity = goodies.users[i].isExpanded ? 0.0 : 1.0
goodies.users[i].isExpanded.toggle()
}
}
}
}
.onDelete(perform: delete)
}
}
}
func delete(at offsets: IndexSet) {
goodies.users.remove(atOffsets: offsets)
}
}
GlobalGoodies class 和用戶 class 的源代碼,改編自HackingWithSwift教程示例。
struct User: Identifiable {
let id = UUID()
var name: String
var children: [User]? = nil
var isExpanded = false
var opacity = 0.0
}
class GlobalGoodies: ObservableObject {
@Published var users = [
User(name: "Paul", children: [
User(name: "Jenny")
]),
User(name: "Taylor", children: [
User(name: "Tyler"),
User(name: "Luna")
]),
User(name: "Adele", children: nil)
]
}
我能夠正常查看這些元素,並且可以毫無問題地刪除兩個(父)項目。 但是,當我嘗試刪除列表中最后一個剩余的(父)元素時,應用程序崩潰並顯示以下消息:
Fatal error: Index out of range: file Swift/ContiguousArrayBuffer.swift, line 444
我知道其他人在使用List
時遇到了相同消息的類似錯誤,但僅在使用此特定設置顯示可擴展子元素時才會出現此錯誤。 我遵循了上面提到的 HackingWithSwift 教程的代碼(這只是一個普通的線性列表),我可以毫無問題地刪除其中的所有元素。
我試過使用新的List(children:)
但是由於某種原因我無法添加onDelete
。
任何查明此錯誤位置的幫助都會很棒,因為我嘗試放置斷點等以查看 go 錯誤的地方。 該元素名義上被刪除,但崩潰似乎發生在調用body
期間或之后。
提前感謝您的幫助!
經過更多的探索,我似乎已經能夠自己弄清楚這一點。 此行發生了超出范圍的錯誤:
DisclosureGroup(isExpanded: $goodies.users[i].isExpanded) {
(我可以通過替換為.constant(true)
來阻止崩潰。)
我能夠通過使用 function 來解決這個問題,它在給定索引i
的情況下提供自定義綁定,它在訪問它之前檢查索引是否在范圍內:
func binding(for index: Int) -> Binding<Bool> {
Binding<Bool>(
get: {
if index > goodies.users.count - 1{
return false
}
return goodies.users[index].isExpanded
},
set: {
if index > goodies.users.count - 1 {
// do nothing
} else {
goodies.users[index].isExpanded = $0
}
}
)
}
受影響線路的用法:
DisclosureGroup(isExpanded: binding(for: i)) {
這解決了崩潰問題。 之前有點難以確定,因為我沒有意識到在刪除列表項后訪問了綁定。 希望這對同一 position 中的人有所幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.