skip to Main Content

I have a list of CoreData Objects retrieved from @FetchRequest. I am looking to animate the re-ordering of a list based on property of the object; a Bool.

In the code below, when you click a row item the view is rebuilt and the order changed, but this happens instantly with no animation, despite the animation on the fetch request.

I have also tried adding an animation to the List and RowView, but this also doesn’t work.


import SwiftUI

struct RowView: View {
    @ObservedObject var place: Place

    var body: some View {
        Button {
            place.visit()
            try? DataController.shared.container.viewContext.save()
        } label: {
            HStack {
                Text(place.wrappedName)
                Spacer()
                place.visited ? Image(systemName: "checkmark.circle.fill") : Image(systemName: "checkmark.circle")
            }
        }
    }
}

struct ListDetailView: View {
    let list: PlaceList

    @FetchRequest var places: FetchedResults<Place>

    init(list: PlaceList) {
        self.list = list
        _places = .init(
            entity: Place.entity(),
            sortDescriptors: [NSSortDescriptor(keyPath: Place.visited, ascending: true)],
            predicate: NSPredicate(format: "list = %@", list),
            animation: .default
        )
    }

    var body: some View {
        VStack {
            Text(self.list.wrappedName)
                .font(.headline)
            List {
                ForEach(places) { place in
                    RowView(place: place)
                }
            }
            .listStyle(.plain)
        }
    }
}

2

Answers


  1. struct ListDetailView: View {
    let list: PlaceList
    
    @FetchRequest var places: FetchedResults<Place>
    
    init(list: PlaceList) {
        self.list = list
        _places = .init(
            entity: Place.entity(),
            sortDescriptors: [NSSortDescriptor(keyPath: Place.visited, ascending: true)],
            predicate: NSPredicate(format: "list = %@", list),
            animation: .default
        )
    }
    
    var body: some View {
        VStack {
            Text(self.list.wrappedName)
                .font(.headline)
            List {
                ForEach(places) { place in
                    RowView(place: place)
                        .animation(.default) // Add animation modifier here
                }
            }
            .listStyle(.plain)
        }
    }
    

    }

    Login or Signup to reply.
  2. You need an animation block eg

    withAnimation {
        place.visit()
        // save if you like
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search