我是Swift和SwiftUI的新手,正在开发一个需要通过各种视图传递嵌套绑定的应用程序。我遇到了一个问题,子视图中的NavigationLink将绑定传递给子详细视图,导致应用程序在真实的设备和模拟器上测试时完全冻结。但是,它不会在SwiftUI预览画布中冻结。
我创建了一个精简的项目来测试这个问题仍然存在。我还尝试通过工作表显示子详细视图,但绑定在工作表视图中不更新。
有谁能看出是否有什么明显的错误导致了这个问题?
ParentDetail视图中的NavigationLink导致冻结。下面是示例代码:
基本型号:
import SwiftUI
class ParentStore: ObservableObject {
@Published var parents = [ParentObject.parentExample]
func binding(for parentID: UUID) -> Binding<ParentObject> {
Binding {
guard let index = self.parents.firstIndex(where: { $0.id == parentID }) else {
fatalError()
}
return self.parents[index]
} set: { updatedParent in
guard let index = self.parents.firstIndex(where: { $0.id == parentID}) else {
fatalError()
}
return self.parents[index] = updatedParent
}
}
}
struct ParentObject: Identifiable {
var id = UUID()
var name: String
var children: [Child]
static let parentExample = ParentObject(name: "Matt", children: [.sasha, .brody])
static let emptyParent = ParentObject(name: "Empty", children: [])
}
struct Child: Identifiable {
var id = UUID()
var name: String
var grandkids: [Grandkid]
static let sasha = Child(name: "Sasha", grandkids: [.peter, .meagan])
static let brody = Child(name: "Brody", grandkids: [.michelle])
}
struct Grandkid: Identifiable {
var id = UUID()
var name: String
static let peter = Grandkid(name: "Peter")
static let meagan = Grandkid(name: "Meagan")
static let michelle = Grandkid(name: "Michelle")
}
主视图:
struct ContentView: View {
@StateObject var parentStore = ParentStore()
var body: some View {
TabView {
ParentList()
.environmentObject(parentStore)
.tabItem {
Label("List", systemImage: "list.bullet")
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
家长名单:
struct ParentList: View {
@EnvironmentObject var parentStore: ParentStore
var body: some View {
NavigationStack {
List {
ForEach($parentStore.parents) { $parent in
NavigationLink(parent.name, value: parent.id)
}
}
.navigationDestination(for: UUID.self) { parentID in
ParentDetail(parent: parentStore.binding(for: parentID))
}
}
}
}
struct ParentList_Previews: PreviewProvider {
static var previews: some View {
ParentList()
.environmentObject(ParentStore())
}
}
ParentDetailView:
struct ParentDetail: View {
@Binding var parent: ParentObject
@State private var child: Binding<Child>?
var body: some View {
List {
Section("Parent") {
Text(parent.name)
}
Section("Children") {
ForEach($parent.children) { $child in
// This navigation link causes the freeze
NavigationLink(child.name) {
ChildDetail(child: $child)
}
// Testing sheet presentation...
Button(child.name) {
self.child = $child
}
}
}
}
.sheet(item: $child) { $child in
ChildDetail(child: $child)
}
}
}
struct ParentDetail_Previews: PreviewProvider {
static var previews: some View {
ParentDetail(parent: .constant(.parentExample))
}
}
子详细视图:
struct ChildDetail: View {
@Binding var child: Child
var body: some View {
VStack {
TextField("Name", text: $child.name)
ForEach(child.grandkids) { grandkid in
Text(grandkid.name)
}
}
}
}
struct ChildDetail_Previews: PreviewProvider {
static var previews: some View {
ChildDetail(child: .constant(.sasha))
}
}
1条答案
按热度按时间relj7zay1#
你需要替换这个:
使用相同的值/目的地新的API,因为你在父母中使用,因为我不认为你可以使用它沿着旧的视图为基础的版本,e。g的。
最好也编辑一下:
我还建议重新构建数据模型,使用
Person
结构体,而不是Parent和Child,它们本质上是一样的。然后,您可以将子ID到ID关系存储在数组中。当使用数据而不是对象的值类型时,我们必须以不同的方式组织事物。