Unable to use transitions for SwiftData in List

I can't for the life of me get transitions and animations to work well with SwiftData and List on MacOS 15 and iOS 18.

I've included an example below, where I define several animations and a transition type, but they are all ignored.

How do I animate items being added to / removed from a List()?

I am attached to List() due to its support for selection, context menu, keyboard shortcuts, etc. If I would switch to ScrollView with VStack I would have to rebuild all of that.

Also, this is super basic and should just work, right?

Thanks for reading.


import SwiftUI
import SwiftData

struct ContentView: View {
    @Environment(\.modelContext) private var modelContext
    
    /// Issues on iOS:
    /// Items animate into and out of view, but I seem to have no control over the animation.
    /// In the code here I've specified a 'bouncy' and a slow 'easeIn' animation: both are not triggered.
    /// The code also specifies using a 'slide' transition, but it is ignored.
    /// -> How do I control the transition and animation timing on iOS?
    ///
    /// Issues on MacOS:
    /// Items do not animate at all on MacOS! They instantly appear and are instantly removed.
    /// -> How do I control the transition and animation timing on MacOS?

    
    // animation added here -> has no effect?
    @Query(animation: .bouncy) private var items: [Item]

    var body: some View {
        VStack {

            Button("Add to list") {
                // called without 'withAnimation' -> no animation
                let newItem = Item(timestamp: Date())
                modelContext.insert(newItem)
            }
            
            List() {
                ForEach(items, id: \.self) { item in
                    Text(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard))
                        .transition(.slide) // items do not slide in/out of view
                        .onTapGesture {
                            // called with 'withAnimation' -> no animation
                            withAnimation(.easeIn(duration: 2)) {
                                modelContext.delete(item)
                            }
                        }
                }
                .animation(.spring(duration: 3), value: items)
            }
        }
        .padding()
    }
}

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



Answered by DTS Engineer in 807994022

The issue is triggered because of the use of SwiftUI List – If you simply comment out the list in your code, as shown below, the animation will work:

//List() {
    ForEach(items, id: \.self) { item in
        Text(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard))
            .transition(.slide) // items do not slide in/out of view
            .onTapGesture {
                // called with 'withAnimation' -> no animation
                withAnimation(.easeIn(duration: 2)) {
                    modelContext.delete(item)
                }
            }
    }
    .animation(.spring(duration: 3), value: items)
//}

SwiftUI List is supposed to automatically manage the animation of its items when they are inserted or deleted. I don’t see a good way that allows you to use SwiftUI List with your own animation. If that is important to your app, you might consider filing a feedback report (http://developer.apple.com/bug-reporting/) for SwiftUI folks to investigate – If you do so, please share your report ID for folks to track.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

Apologies, the following model code is also needed for the sample code to work:

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

The issue is triggered because of the use of SwiftUI List – If you simply comment out the list in your code, as shown below, the animation will work:

//List() {
    ForEach(items, id: \.self) { item in
        Text(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard))
            .transition(.slide) // items do not slide in/out of view
            .onTapGesture {
                // called with 'withAnimation' -> no animation
                withAnimation(.easeIn(duration: 2)) {
                    modelContext.delete(item)
                }
            }
    }
    .animation(.spring(duration: 3), value: items)
//}

SwiftUI List is supposed to automatically manage the animation of its items when they are inserted or deleted. I don’t see a good way that allows you to use SwiftUI List with your own animation. If that is important to your app, you might consider filing a feedback report (http://developer.apple.com/bug-reporting/) for SwiftUI folks to investigate – If you do so, please share your report ID for folks to track.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

Just to clarify, although I see that List + default animation works on iOS, I don't see the same configuration presents any animation on macOS.

If you target to support macOS, I'd again suggest that you file a feedback report to hopefully gain more attentions from the SwiftUI team.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

I have filed feedback to report this bug (FB15436970). Thanks for taking a look!

Unable to use transitions for SwiftData in List
 
 
Q