核心数据CloudKit-列表未完成后不更新OnMove排序

发布于 2025-01-27 14:03:21 字数 2945 浏览 7 评论 0原文

我有一个核心数据 + CANTKIT应用程序,在点击完成按钮后,通过OnMove修饰符进行的任何更改(排序订单)将不会直接显示。如果我离开视野并回来,则可以看到更改。我尝试在OnMove功能期间获取新的更新项目,但这会产生奇怪的行为。

我有以下persistencecontroller:

static let shared = PersistenceController()
    
let container: NSPersistentCloudKitContainer
    
var context: NSManagedObjectContext {
    return container.viewContext
}
    
init(inMemory: Bool = false) {
        
    container = NSPersistentCloudKitContainer(name: "MonnyModel")
        
    if inMemory {
        container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
    }
        
    container.loadPersistentStores { storeDescription, error in
        if let error = error as NSError? {
            // Replace this implementation with code to handle the error appropriately.
            fatalError("Unresolved error \(error), \(error.userInfo)")
        }
    }
        
    context.automaticallyMergesChangesFromParent = true
    context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
        
    try? context.setQueryGenerationFrom(.current)
}
...

我的ViewModel:

@Published var lists: [Listing] = []
    
func fetchAllLists() {
    lists = PersistenceController.shared.fetchLists()
}
    
...
    
func move(from source: IndexSet, to destination: Int) {
        
    // Make an array of items from fetched results
    var revisedLists: [Listing] = lists.map{$0}
        
    // Change the order of the items in the array
    revisedLists.move(fromOffsets: source, toOffset: destination)
        
    // Update the sortOrder attribute in revisedLists to persist the new order. This is done in reverse order to minimize changes to the indices.
    for reverseIndex in stride(from: revisedLists.count - 1, through: 0, by: -1) {
        revisedLists[reverseIndex].sortOrder = Int16(reverseIndex + 1)
    }

    // I've tried fetching it here which causes strange behaviour

    PersistenceController.shared.save()
}

我尝试在移动功能中再次获取,但这无效。这样做将使列表上的EditMode保持活动状态,但是每行的所有操作都消失了,我唯一能做的就是点击完成按钮。我还尝试了.objectWillChange.Send(),但是正在发生同样的奇怪行为。

这是我观点中的列表:

struct MyListView: View {
    
    @Environment(\.managedObjectContext) private var viewContext
    
    @StateObject var viewModel: ListViewModel
    
    var body: some View {
        List {
            ForEach(viewModel.lists.sorted(by: { $0.sortOrder < $1.sortOrder })) { list in
                ListCellView(viewModel: viewModel, list: list)
            }
            .onMove(perform: viewModel.move)
            .onDelete(perform: { indexSet in
                indexSet.forEach { index in
                    viewModel.deleteList(list: viewModel.lists[index])
                    viewModel.fetchAllLists()
                }
            })
        }
        .onAppear {
            viewModel.fetchAllLists()
        }
        .refreshable {
            viewModel.fetchAllLists()
        }
    }
}

I have a Core Data + CouldKit App where any changes made(sort order) via the onMove modifier will not show directly after tapping the done button. If I leave the view and come back the change is visible. I tried fetching the new updated items during the onMove function but this will create strange behaviours.

I have the following PersistenceController:

static let shared = PersistenceController()
    
let container: NSPersistentCloudKitContainer
    
var context: NSManagedObjectContext {
    return container.viewContext
}
    
init(inMemory: Bool = false) {
        
    container = NSPersistentCloudKitContainer(name: "MonnyModel")
        
    if inMemory {
        container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
    }
        
    container.loadPersistentStores { storeDescription, error in
        if let error = error as NSError? {
            // Replace this implementation with code to handle the error appropriately.
            fatalError("Unresolved error \(error), \(error.userInfo)")
        }
    }
        
    context.automaticallyMergesChangesFromParent = true
    context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
        
    try? context.setQueryGenerationFrom(.current)
}
...

My ViewModel:

@Published var lists: [Listing] = []
    
func fetchAllLists() {
    lists = PersistenceController.shared.fetchLists()
}
    
...
    
func move(from source: IndexSet, to destination: Int) {
        
    // Make an array of items from fetched results
    var revisedLists: [Listing] = lists.map{$0}
        
    // Change the order of the items in the array
    revisedLists.move(fromOffsets: source, toOffset: destination)
        
    // Update the sortOrder attribute in revisedLists to persist the new order. This is done in reverse order to minimize changes to the indices.
    for reverseIndex in stride(from: revisedLists.count - 1, through: 0, by: -1) {
        revisedLists[reverseIndex].sortOrder = Int16(reverseIndex + 1)
    }

    // I've tried fetching it here which causes strange behaviour

    PersistenceController.shared.save()
}

I've tried fetching again in the move function but that didn't work. Doing this will keep the editMode on the list active but all the actions on each row disappear and the only thing I could do is to tap on the done button. I've also tried .objectWillChange.send() here but same strange behaviour is happening.

Here is the list in my View:

struct MyListView: View {
    
    @Environment(\.managedObjectContext) private var viewContext
    
    @StateObject var viewModel: ListViewModel
    
    var body: some View {
        List {
            ForEach(viewModel.lists.sorted(by: { $0.sortOrder < $1.sortOrder })) { list in
                ListCellView(viewModel: viewModel, list: list)
            }
            .onMove(perform: viewModel.move)
            .onDelete(perform: { indexSet in
                indexSet.forEach { index in
                    viewModel.deleteList(list: viewModel.lists[index])
                    viewModel.fetchAllLists()
                }
            })
        }
        .onAppear {
            viewModel.fetchAllLists()
        }
        .refreshable {
            viewModel.fetchAllLists()
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

我不是你的备胎 2025-02-03 14:03:21

我已经通过添加

.environment(\。editmode,self。$ iseditMode)

在我的列表中添加nodmode)来解决我的问题。

使用此变量@State var iseditMode:editmode = .Inactive

I've managed to fix my issue by adding

.environment(\.editMode, self.$isEditMode)

to my List in the view where the Editbutton() is located.

With this variable @State var isEditMode: EditMode = .inactive

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文