如何使用 SwiftUI 和 CoreData 制作动态列表排序动画 (@FetchRequest)

Dov*_*izu 8 core-data swift swiftui swiftui-animation

我有一个显示 CoreData FetchRequest 的列表,并且有一个可以更改列表排序方式的选取器。我目前的实现方式如下:

struct ParentView: View {
    enum SortMethod: String, CaseIterable, Identifiable {
        var id: Self { self }
        
        case byName = "Name"
        case byDateAdded = "Date Added"
    }

    @State private var currentSortMethod = SortMethod.byName

    var body: some View {
        ItemListView(sortMethod: currentSortMethod) // See child view implementation below
        .toolbar {
            ToolbarItem(placement: .principal) {
                Picker("Sort by", selection: $currentSortMethod) {
                    ForEach(SortMethod.allCases) { sortMethod in
                        Text(sortMethod.rawValue)
                    }
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

子视图如下所示:

struct ItemListView: View {
    
    @Environment(\.managedObjectContext) private var managedObjectContext
    @FetchRequest var items: FetchedResults<Item>
    
    init(sortMethod: ParentView.SortMethod) {
        let sortDescriptor: NSSortDescriptor
        switch sortMethod {
        case .byName:
            sortDescriptor = NSSortDescriptor(keyPath: \Item.name, ascending: true)
        case .byDateAdded:
            sortDescriptor = NSSortDescriptor(keyPath: \Item.dateAdded, ascending: true)
        }
        _items = .init(
            entity: Item.entity(),
            sortDescriptors: [sortDescriptor],
            predicate: nil,
            animation: .default
        )
    }
    
    var body: some View {
        List {
            ForEach(items) { item in
                SingleItemView(item)
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,当我更改排序选项时,列表不会对重新排序进行动画处理(可能是因为整个列表ItemListView正在重建)。如果我在父视图中添加.animation(.default)ItemListView()则列表在重新排序时会产生动画效果,但从导航回来时也会有奇怪的动画其他视图。我似乎不知道在哪里可以添加块withAnimation { }。或者是否有更好的方法,使 SwiftUI 更自然,从而允许一些默认动画?

Asp*_*eri 4

绑定可以附加动画,因此请尝试以下操作(或使用您想要的任何动画参数)

Picker("Sort by", selection: $currentSortMethod.animation())  // << here !!
Run Code Online (Sandbox Code Playgroud)