如何使用预定义的项目数组获取模型并在 SwiftUI 中进行更新和删除

问题描述 投票:0回答:1

我是 swiftui 新手,我正在尝试加载模型中定义的数组,当您打开新项目时,我已经从 xcode 中调整了示例代码。就我而言,我想加载已成功加载的日期数组,但当我从模型中删除项目时,deleteItems 函数显示索引错误。

无法分配给属性:“items”是仅获取属性

在这部分代码中,类型“Item”没有成员“all”):items = try modelContext.fetch(Item.all()

以及 testApp 代码中的另一个错误:

线程 1:“无效更新:第 0 节中的项目数无效。更新后现有节中包含的项目数 (3) 必须等于更新前该节中包含的项目数 (2),加上或减去从该部分插入或删除的项目数(0 插入,0 删除)以及加上或减去移入或移出该部分的项目数(0 移入,0 移出)。集合视图:;背景颜色 = ;图层 = ;contentOffset:{0, -92};contentSize:{414, 143};调整后的ContentInset:{92, 0, 34, 0};布局:;数据源:<_TtGC7SwiftUI31UICollectionViewListCoordinatorGVS_28CollectionViewListDataSourceOs5Never_GOS_19SelectionManager")

import Foundation
import SwiftData

@Model
class Item: Identifiable {
    var timestamp: Date
    
    init(timestamp: Date) {
        self.timestamp = timestamp
    }

    // Define a static array of pre-defined dates
    static let preDefinedDates: [Date] = [
        Date(),
        Date().addingTimeInterval(86400), // Adding one day
        Date().addingTimeInterval(2 * 86400) // Adding two days
    ]
}




import SwiftUI
import SwiftData

@main
struct testApp: App {
    var sharedModelContainer: ModelContainer = {
        let schema = Schema([
            Item.self,
        ])
        let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false)

        do {
            return try ModelContainer(for: schema, configurations: [modelConfiguration])
        } catch {
            fatalError("Could not create ModelContainer: \(error)")
        }
    }()

    var body: some Scene {
        WindowGroup {
            ContentView()
                .modelContainer(sharedModelContainer)
        }
        .modelContainer(sharedModelContainer)
    }
}

这是查看代码:

import SwiftUI
import SwiftData


struct ContentView: View {
    @Environment(\.modelContext) private var modelContext
    @Query private var items: [Item] = []

    var body: some View {
        NavigationSplitView {
            List {
                ForEach(Item.preDefinedDates, id: \.self) { predefinedDate in
                    NavigationLink {
                        Text("Item at \(predefinedDate, format: Date.FormatStyle(date: .numeric, time: .standard))")
                    } label: {
                        Text(predefinedDate, format: Date.FormatStyle(date: .numeric, time: .standard))
                    }
                }
                .onDelete(perform: deleteItems)
            }
            .toolbar {
                ToolbarItem(placement: .navigationBarTrailing) {
                    EditButton()
                }
                ToolbarItem {
                    Button(action: addItem) {
                        Label("Add Item", systemImage: "plus")
                    }
                }
            }
        } detail: {
            Text("Select an item")
        }
    }

    private func addItem() {
        withAnimation {
            let newItem = Item(timestamp: Date())
            modelContext.insert(newItem)
        }
    }

    private func deleteItems(offsets: IndexSet) {
        withAnimation {
            // Print the items array and offsets for debugging
            print("Items before deletion: \(items)")
            print("Offsets to delete: \(offsets)")

            for index in offsets {
                guard index < items.count else {
                    print("Index out of range: \(index)")
                    continue
                }

                let itemToDelete = items[index]
                modelContext.delete(itemToDelete)
            }

            do {
                try modelContext.save()

                // Update the items array after deletion
                items = try modelContext.fetch(Item.all())
                print("Items after deletion: \(items)")
            } catch {
                print("Error saving after deletion: \(error)")
            }
        }
    }

}

#Preview {
    ContentView()
        .modelContainer(for: Item.self, inMemory: true)
}

我希望它会删除该项目,并且在重新启动应用程序后不再在列表中显示它

your

arrays swiftui save swift-data
1个回答
0
投票

我尝试运行你的代码,但出现了一堆奇怪的错误,这是由于你没有完全理解如何使用 SwiftUI、SwiftData 或数据源造成的。因此,首先,如果您正在学习 SwiftUI,那么不要使用 SwiftData,因为同时学习两者太多了。

首先,您要混合两个完全独立的数据源,即静态数组和持久模型

Item

您应该做的第一件事是从项目中删除

Item
以及与 SwiftData 相关的任何内容。

然后,为了使数组成为视图代码的正确数据源,请将其移动到内容视图中并将其转换为

@State
属性

@State private var preDefinedDates: [Date] = [
    Date(),
    Date().addingTimeInterval(86400), // Adding one day
    Date().addingTimeInterval(2 * 86400) // Adding two days
]

将删除功能更改为

private func deleteItems(offsets: IndexSet) {
    withAnimation {
        preDefinedDates.remove(atOffsets: offsets)        
    }
}

并更改或删除

addItem()
函数,如果您已删除所有 SwiftData 代码,您现在可以运行您的应用程序,删除将按预期工作。

如果您坚持还使用 SwiftData,那么您需要执行相反的操作,删除静态数组并使用您今天使用数组的查询属性

items
。请注意,
@Query
将使数组保持最新,您不需要手动执行此操作。

© www.soinside.com 2019 - 2024. All rights reserved.