为什么 SwiftUI 在删除索引后以不同方式为列表项设置动画?

Why does SwiftUI animate List items differently after index removed?

我真的很难理解为什么会这样,我很茫然。

情况似乎是动画根据某个项目是否先前存在于动画项目占用的数组索引处而有所不同。

这是我使用的代码:

  @FetchRequest(
    sortDescriptors: [NSSortDescriptor(keyPath: \Profile.lastUsed, ascending: true)],
    animation: .spring()
  )
  private var profiles: FetchedResults<Profile>

  var body: some View {
    List() {
      ForEach(profiles, id: \.id) { profile in
        ProfileView(profile)
      }
    }
    .listStyle(InsetListStyle())
    .toolbar {
      Button(action: addItem) {
        Label("Add Item", systemImage: "plus")
      }
      Button(action: deleteItem) {
        Label("Remove Items", systemImage: "minus")
      }
    }
  }
  
  private func addItem() {
      let profile = Profile(context: viewContext)
      profile.id = UUID()
      profile.lastUsed = Date()
      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 deleteItem() {
    if profiles.last != nil { viewContext.delete(profiles.last!) }
    
    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)")
    }
  }

struct ProfileView: View {
  @State var isPopover = false
  var profile: Profile;
  
  init(_ profile: Profile) {
    self.profile = profile;
  }
  
  var body: some View {
    Button(action: { self.isPopover.toggle() }) {
      ZStack(alignment: .leading) {
        RoundedRectangle(cornerRadius: 5, style: .continuous)
          .fill(Color(NSColor.separatorColor).opacity(0.75))
        VStack(alignment: .leading) {
          Text("\(profile.id!)").font(.headline)
          Text("Profile last used \(profile.lastUsed!, formatter: itemFormatter)").font(.body)
        }.padding(12)
      }
    }
    .buttonStyle(PlainButtonStyle())
    .padding(.bottom, 8)
    .popover(isPresented: self.$isPopover, arrowEdge: .trailing) {
       PopoverView()
    }
  }
}

效果可见here

我不确定我是否遗漏了一些信息,或者这是一个错误,因为这是在 Big Sur Beta 4 上。

尝试以下...

  var body: some View {
    Button(action: { self.isPopover.toggle() }) {
      ZStack(alignment: .leading) {
        RoundedRectangle(cornerRadius: 5, style: .continuous)
          .fill(Color(NSColor.separatorColor).opacity(0.75))
        VStack(alignment: .leading) {
          Text("\(profile.id!)").font(.headline)
          Text("Profile last used \(profile.lastUsed!, formatter: itemFormatter)").font(.body)
        }.padding(12)
      }
    }
    .buttonStyle(PlainButtonStyle())
    .padding(.bottom, 8)
    .animation(nil)          // << here !!
...