列表重新排序后 SwiftUI 关闭

Posted

技术标签:

【中文标题】列表重新排序后 SwiftUI 关闭【英文标题】:SwiftUI dismiss after list reorder 【发布时间】:2021-10-14 18:08:24 【问题描述】:

我正在尝试重新排序我的 CoreData 项目,但是当我尝试重新排序项目并放置单元格时,我的列表视图被关闭。所有更改都会保存并正确显示在其他视图和修改的列表中。 这是我的代码

import SwiftUI

struct DaysOrderView: View 
    
    @Environment(\.managedObjectContext) var moc
    @FetchRequest(entity: Days.entity(), sortDescriptors:[NSSortDescriptor(key: "id", ascending: true)]) var days : FetchedResults<Days>
    
    var body: some View 
        List 
            ForEach(days, id: \.self )  day in
                HStack 
                    Image(systemName: day.isDisplayed.boolValue ? "checkmark.circle.fill" : "checkmark.circle").foregroundColor(.yellow)
                    Text(day.name)
                
            
            .onMove(perform: onMove)
        
            .toolbar 
                EditButton()
            
    
    
    private func onMove(source: IndexSet, destination: Int) 
            
        var revisedItems: [ Days ] = days.map $0 
        
            revisedItems.move(fromOffsets: source, toOffset: destination )
        
            for reverseIndex in stride( from: revisedItems.count - 1,
                                        through: 0,
                                        by: -1 )
            
                    revisedItems[ reverseIndex ].id = Int16( reverseIndex )
            
    

【问题讨论】:

欢迎来到 Stack Overflow!您是否希望有一些任意的排序顺序? 是的,我希望它按 id 排序。 【参考方案1】:

id 不是任意的,更改 id 以更改排序顺序可能会产生后果。如果您想要一个可更改的顺序,我建议您使用专用于排序顺序的属性来跟踪它并更改它。

我使用sortOrder 属性和id 属性组合了一个快速应用程序。当我使用 'idas anInt16` 并对其进行排序和更改时,出现以下错误:

ForEach>: ID 2 在集合中出现多次,这将给出 未定义的结果!

将其换成sortOrder 属性没有出现错误。由于您没有使用 Core Data 发布整个代码,这是可以理解的,因此我不能 100% 确定,但我敢打赌您的问题归结为这个问题。此外,您应该将您的 id 设为 UUID(),这就是它存在的目的,并且不要更改 id。这就像有多个孩子的父母每天交换孩子的名字一样。它可能有效,但很可能是混乱。

FWIW 用于测试的代码:

struct ContentView: View 
    @Environment(\.managedObjectContext) private var viewContext

    @FetchRequest(
        sortDescriptors: [NSSortDescriptor(keyPath: \Item.sortOrder, ascending: true)],
        animation: .default)
    private var items: FetchedResults<Item>

    var body: some View 
        NavigationView 
            List 
                ForEach(items)  item in
                    NavigationLink 
                        Text("Item \(item.sortOrder) at \(item.timestamp!, formatter: itemFormatter)")
                     label: 
                        Text(item.timestamp!, formatter: itemFormatter)
                    
                
                .onDelete(perform: deleteItems)
                .onMove(perform: onMove)
            
            .toolbar 
                ToolbarItem(placement: .navigationBarTrailing) 
                    EditButton()
                
                ToolbarItem 
                    Button(action: addItem) 
                        Label("Add Item", systemImage: "plus")
                    
                
            
            Text("Select an item")
        
    

    private func addItem() 
        withAnimation 
            let newItem = Item(context: viewContext)
            newItem.timestamp = Date()
            newItem.id = UUID()
            newItem.sortOrder = Int16(items.count)

            do 
                try viewContext.save()
             catch 
                // Replace this implementation with code to handle the error appropriately.
                // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
                let nsError = error as NSError
                fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
            
        
    

    private func deleteItems(offsets: IndexSet) 
        withAnimation 
            offsets.map  items[$0] .forEach(viewContext.delete)

            do 
                try viewContext.save()
             catch 
                // Replace this implementation with code to handle the error appropriately.
                // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
                let nsError = error as NSError
                fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
            
        
    
    
    private func onMove(source: IndexSet, destination: Int) 
            
        var revisedItems: [ Item ] = items.map $0 
        
            revisedItems.move(fromOffsets: source, toOffset: destination )
        
            for reverseIndex in stride( from: revisedItems.count - 1,
                                        through: 0,
                                        by: -1 )
            
                    revisedItems[ reverseIndex ].sortOrder = Int16( reverseIndex )
            
    


这是我添加属性的基本“使用核心数据”代码。

【讨论】:

不幸的是,这并没有解决问题。重新排序后视图仍然关闭:/

以上是关于列表重新排序后 SwiftUI 关闭的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI 模式表在关闭后重新打开

如何允许对不在编辑模式下的 SwiftUI 列表中的行进行重新排序?

SwiftUI - iPad 上的拖放重新排序是不是可以在没有 EditMode 的情况下工作?

UICollectionView 与 SwiftUI + 拖放重新排序可能吗?

SwiftUI 嵌套列表不出现

SwiftUI 如何在横向和纵向中重新排序