SwiftUI UItableView被告知在不使用视图层次结构的情况下布局其可见单元格和其他内容

Ara*_*ash 6 warnings list view-hierarchy swiftui

我在视图中有一个列表(将其称为视图A),在其中我通过导航链接从视图A推入视图B,并将CurrentSubjectValue操纵到初始视图A。添加数据并添加didChangd.send(value)分派到视图AI的警告是更新不属于视图的单元格。似乎从窗口中删除了视图A,这基于我以前的uinavigationviewcontroller行为是不直观的。任何的想法?

视图A(MainView)

struct MainView: View {

    @ObjectBinding var currentProfileIdStore = CurrentProfileIdStore.shared

    var body: some View {

        NavigationView {
            if (currentProfileIdStore.didChange.value == nil) {
                NavigationLink(destination: ProfilesView()){ Text("show profiles view")}
            } else {
                List {
                    Section {
                        ForEach(0..<1) { _ in
                            PresentationLink(destination: ProfilesView()) {
                                Text("Profiles")
                            }
                        }
                    }

                    Section {
                        ForEach(0..<1) { _ in
                            Text("Items")
                        }
                    }
                }.listStyle(.grouped)
            }
        }.navigationBarTitle(currentProfileIdStore.didChange.value ?? "unknown")

    }
}
Run Code Online (Sandbox Code Playgroud)

然后显示配置文件视图

struct ProfilesView : View {

    @ObjectBinding var profileManager = CurrentProfileIdStore.shared
    @ObjectBinding var profileProvider = ProfileProvider.shared

    var body: some View {

        NavigationView {

            List {
                Section {
                    ForEach(0..<1) { _ in
                        NavigationLink(destination: NewProfile()) {
                            Text("Add Profile")
                        }
                    }
                }


                Section {
                    ForEach(self.profileProvider.didChange.value) { profile in
                        VStack {

                            if profile.id == self.profileManager.didChange.value {
                                Image(systemName: "g.circle").transition(.move(edge: .top))
                            }

                            ProfileCellView(profile: profile)
                            Text(self.profileManager.didChange.value ?? "unknown").font(.footnote).color(.secondary)
                        }
                    }
                }

            }
            .navigationBarTitle("Profiles")
                .listStyle(.grouped)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我们可以添加一个新的配置文件

struct MainView: View {

    @ObjectBinding var currentProfileIdStore = CurrentProfileIdStore.shared

    var body: some View {

        NavigationView {
            if (currentProfileIdStore.didChange.value == nil) {
                NavigationLink(destination: ProfilesView()){ Text("show profiles view")}
            } else {
                List {
                    Section {
                        ForEach(0..<1) { _ in
                            PresentationLink(destination: ProfilesView()) {
                                Text("Profiles")
                            }
                        }
                    }

                    Section {
                        ForEach(0..<1) { _ in
                            Text("Items")
                        }
                    }
                }.listStyle(.grouped)
            }
        }.navigationBarTitle(currentProfileIdStore.didChange.value ?? "unknown")

    }
}
Run Code Online (Sandbox Code Playgroud)

然后有提供者

struct ProfilesView : View {

    @ObjectBinding var profileManager = CurrentProfileIdStore.shared
    @ObjectBinding var profileProvider = ProfileProvider.shared

    var body: some View {

        NavigationView {

            List {
                Section {
                    ForEach(0..<1) { _ in
                        NavigationLink(destination: NewProfile()) {
                            Text("Add Profile")
                        }
                    }
                }


                Section {
                    ForEach(self.profileProvider.didChange.value) { profile in
                        VStack {

                            if profile.id == self.profileManager.didChange.value {
                                Image(systemName: "g.circle").transition(.move(edge: .top))
                            }

                            ProfileCellView(profile: profile)
                            Text(self.profileManager.didChange.value ?? "unknown").font(.footnote).color(.secondary)
                        }
                    }
                }

            }
            .navigationBarTitle("Profiles")
                .listStyle(.grouped)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

请记住,多个视图共享同一提供者主题。因此,当添加新的配置文件时,就会发生此问题。

self.profileProvider.addProfile(new
Run Code Online (Sandbox Code Playgroud)

还有另外两个问题,一个问题是,当回到mainView后,该按钮不再起作用。另外,当以模态展示时,我还不知道如何手动返回。

Whi*_*bit 1

查看您的代码,您应该考虑解决以下一些问题:

SwiftUI Life CycleBindableObjectSwiftUI life cycle和 视图刷新方式可能与 略有不同UIKit。在 中SwiftUI,视图应该是轻量级且可重新创建的,因此视图会经常刷新。您的警告可能源于SwiftUI尝试更新不再位于当前层次结构中的视图。

另外,请记住SwiftUI 2.0引入了新的 ObservableObject 协议来取代BindableObject. 通过这样做,您可能会更改视图侦听数据更改的方式。

在嵌套中NavigationView,您应该避免将 a 嵌套NavigationView在另一个中NavigationView。这可能会导致不需要的行为,并可能影响导航堆栈删除嵌套NavigationView,系统应该为您处理导航。

手动返回。如果您希望手动弹出视图,可以使用@Environment(\.presentationMode)变量,并调用其wrappedValue.dismiss()方法来手动关闭视图。

也许我在下面概述的几点可以帮助解决您的一些问题:

  1. 更新可观察模式:替换@ObjectBinding@ObservedObject和。使用属性包装器来表示您希望视图观察的属性。BindableObjectObservableObject@Published

请参阅下面我的示例:


class ProfileProvider: ObservableObject {
    @Published var profiles: [Profile] = []
    ...

}

Run Code Online (Sandbox Code Playgroud)

然后,在视图中你可以做这样的事情:


@ObservedObject var profileProvider = ProfileProvider.shared
Run Code Online (Sandbox Code Playgroud)
  1. 删除 NestedNavigationViews并仅保留最外面的NavigationView.

  2. 在您的 NewProfile 视图中尝试如下操作:


@Environment(\.presentationMode) var presentationMode

...

if self.successfullyAdded  {
    Text("Successfully added, please go back manually :)")
        .lineLimit(nil)
    Button("Go Back") {
        self.presentationMode.wrappedValue.dismiss()
    }
}
Run Code Online (Sandbox Code Playgroud)
  1. 更新视图时,SwiftUI 视图应该反映您的数据。如果数据发生变化,视图应该自动更新。如果不这样做,请考虑重新审视数据流以及视图的结构。

  2. 使用时请NavigationLink记住,它NavigationLink有一个isActive可用于以编程方式弹出视图的绑定。

对于 中的不起作用的按钮MainView,可能是由于您设置的逻辑是否应显示它。考虑简化该部分并在添加更多逻辑之前首先使用静态视图进行测试。

SwiftUI与 UIKit 相比,它提倡不同的思维方式。专注于确保您的数据驱动您的 UI。一旦您的数据和逻辑设置正确,它们UI应该会自动反映更改。

尝试确保所有视图都是轻量级的且易于重新创建,并且您的数据源(例如ObservableObject实例)能够正确通知视图更改。

希望这有助于解决您的问题 =)