【问题标题】:Why Animation doesn't work inside a child view passed by Binding?为什么动画在 Binding 传递的子视图中不起作用?
【发布时间】:2022-11-11 05:07:27
【问题描述】:

编辑:

我找到了一个解决方案,但我真的很想知道它为什么会这样,因为我通过简单的反复试验得到了解决方案。

我找到的解决方案是在子视图的列表中添加.animation(.default, value: user.times) 修饰符。为什么它会这样工作,我不知道。

我有一个奇怪的问题,当我将绑定传递给子视图时,除了.onDelete 修饰符之外,该子视图内的更改没有动画。

这是产生此问题的简化代码:

Observable(ViewModel) 和模型结构:

extension ContentView {
    class ViewModel: ObservableObject {
        @Published var users = [User]()

        func createUser() {
            users.append(User(times: []))
        }
    }

    struct User: Equatable {
        let name = UUID().uuidString
        var times: [Date]
    }
}

ContentView:(父视图)

struct ContentView: View {
    @StateObject var vm = ViewModel()

    var body: some View {
        NavigationView {
            List {
                ForEach(vm.users.indices, id: \.self) { index in
                    NavigationLink {
                        UserView(user: $vm.users[index])
                    } label: {
                        Text(vm.users[index].name)
                    }
                }
                .onDelete { offsets in
                    vm.users.remove(atOffsets: offsets)
                }
                Button("Add") {
                    withAnimation {
                        vm.createUser()
                    }
                }
            }
            .navigationTitle("Parent View")
        }
    }
}

UserView(儿童视角):

struct UserView: View {
    @Binding var user: ContentView.User

    var body: some View {
        List {
            ForEach(user.times.indices, id: \.self) { index in
                Text(user.times[index].description)
            }
            .onDelete { offsets in
                user.times.remove(atOffsets: offsets)
            }
            Button {
                withAnimation {
                    user.times.append(Date())
                }
            } label: {
               Text("Add Time")
            }

        }
        .navigationTitle("Child View")
    }
}

请注意,在下图中,除了绑定之外,具有几乎完全相同代码的父视图正在按预期工作和动画,并注意子视图 .onDelete 修饰符也在按预期设置动画,但是当添加到子视图列表时,动画不工作。

谢谢!

【问题讨论】:

  • 问题是每当子视图将新日期附加到其times 数组时,父视图的列表就会重新加载。我不认为有一种动画方式将项目添加到子视图的列表中。每当列表项更改时,SwiftUI 都会重新加载整个列表,在您的情况下,这会导致父视图和子视图都重新加载。
  • 谢谢@Anwuna!我实际上找到了一种解决方法,但我真的不知道为什么它会这样工作。我会更新我的问题,看看人们是否能明白为什么它会这样。

标签: ios arrays swift swiftui observableobject


【解决方案1】:

我相当确定问题出在.indices 的使用上,因为id: .self 现在引用索引数组[Int] 中的Int 而不是[User] 数组中的User 对象,

如果我没记错的话,一个解决方案是to use enumerated(),方法如下:

ForEach(Array(array.enumerated()), id: .offset) { index, element in
  // ...
}

【讨论】:

    猜你喜欢
    • 2012-01-31
    • 1970-01-01
    • 2017-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-29
    • 2020-08-29
    • 1970-01-01
    相关资源
    最近更新 更多