Ios 将绑定传递回父级';父视图
我有4种观点Ios 将绑定传递回父级';父视图,ios,swiftui,Ios,Swiftui,我有4种观点 祖父母 母公司 孩子 编辑视图 祖父母有一个指向父母的导航链接,而父母有一个指向孩子的导航链接。Child有一个按钮,通过父级中的绑定和子级中的绑定从祖父母那里初始化@State变量location(一个类)。该按钮还更新了祖父母的@State变量showEditView(再次通过绑定),其中显示了EditView 目前有11行被注释掉了。如果它们被注释掉,当我点击子视图中的按钮时,应用程序会抛出一个“致命错误:意外发现零…”错误。如果任一部分未注释,则按钮不会引发错误 如果我将绑
import SwiftUI
struct Grandparent: View {
@State var location: Location!
@State var showEditView: Bool = false
var body: some View {
NavigationView {
VStack{
NavigationLink(
destination: Parent(location: $location, showEditView: $showEditView)) {
Text("Navigate")
}
// // section 1
// if location != nil {
// Text(location.name)
// } else {
// Text("No location yet")
// }
}
// // section 2
// .navigationBarItems(trailing:
// Button("Edit"){
// showEditView = true
// }
// .disabled(location == nil)
// )
}
.padding()
.sheet(isPresented: $showEditView) {
EditView(placemark: location, dismiss: { showEditView = false })
}
}
}
母公司
import SwiftUI
struct Parent: View {
@Binding var location: Location!
@Binding var showEditView: Bool
var body: some View {
NavigationLink(
destination: Child(location: $location, showEditView: $showEditView),
label: {
Text("Child")
})
}
}
孩子
编辑视图
import SwiftUI
struct EditView: View {
@ObservedObject var placemark: Location
var dismiss: () -> Void
var body: some View {
NavigationView {
Text(placemark.name)
.navigationTitle("Edit place")
.navigationBarItems(trailing: Button("Done") { dismiss() })
}
}
}
位置
import Foundation
class Location: ObservableObject {
init(name: String) {
self.name = name
}
@Published var name: String
}
您可能不应该将您的
位置
声明为
然后执行nil
检查。使用代码>是一种要求崩溃发生的行为。我认为您遇到的是在设置位置之前渲染工作表
。对于在运行循环中何时设置@State
变量没有任何保证,因此最好考虑为nil
的情况(并且绝对不要使用!
强制展开它)
其次,至少考虑到这里的场景,您可能不应该为位置使用类
——它应该是一个结构
最终,您将遇到一点复杂性,因为根据视图的名称判断,您希望在某个时候编辑位置。使用可选
,这变得有点棘手,因为文本字段
之类的内容需要非可选值,但这可以在各种was中解决(请参阅我使用的非零绑定
)
这样做肯定比你现在做的更安全。这可能不是你想要的,但希望它能让你走上正确的道路
struct Location {
var name : String
}
struct Grandparent: View {
@State var location: Location?
@State var showEditView: Bool = false
var body: some View {
NavigationView {
VStack{
NavigationLink(
destination: Parent(location: $location, showEditView: $showEditView)) {
Text("Navigate")
}
if let location = location {
Text(location.name)
} else {
Text("No location yet")
}
}
.padding()
.sheet(isPresented: $showEditView) {
EditView(placemark: $location, dismiss: { showEditView = false })
}
}
}
}
struct Parent: View {
@Binding var location: Location?
@Binding var showEditView: Bool
var body: some View {
NavigationLink(
destination: Child(location: $location, showEditView: $showEditView),
label: {
Text("Child")
})
}
}
struct Child: View {
@Binding var location: Location?
@Binding var showEditView: Bool
var body: some View {
Button("Make location") {
location = Location(name: "Lebanon")
showEditView = true
}
}
}
struct EditView: View {
@Binding var placemark: Location?
var dismiss: () -> Void
var nonNilBinding : Binding<Location> {
.init { () -> Location in
placemark ?? Location(name:"Default")
} set: { (newValue) in
placemark = newValue
}
}
var body: some View {
NavigationView {
TextField("Name", text: nonNilBinding.name)
.navigationTitle("Edit place")
.navigationBarItems(trailing: Button("Done") { dismiss() })
}
}
}
结构位置{
变量名称:String
}
结构祖父母:视图{
@状态变量位置:位置?
@状态变量showEditView:Bool=false
var body:一些观点{
导航视图{
VStack{
导航链接(
目的地:父级(位置:$location,showEditView:$showEditView)){
文本(“导航”)
}
如果let location=location{
文本(location.name)
}否则{
文本(“还没有位置”)
}
}
.padding()
.sheet(显示:$showEditView){
EditView(placemark:$location,dismise:{showEditView=false})
}
}
}
}
结构父级:视图{
@绑定变量位置:位置?
@绑定变量showEditView:Bool
var body:一些观点{
导航链接(
目的地:子级(位置:$location,showEditView:$showEditView),
标签:{
文本(“儿童”)
})
}
}
结构子级:视图{
@绑定变量位置:位置?
@绑定变量showEditView:Bool
var body:一些观点{
按钮(“制作位置”){
地点=地点(名称:“黎巴嫩”)
showEditView=true
}
}
}
结构编辑视图:视图{
@绑定变量placemark:位置?
var DISCLISE:()->Void
var nonNilBinding:Binding{
.init{()->中的位置
placemark??位置(名称:“默认”)
}集合:{(newValue)在
placemark=newValue
}
}
var body:一些观点{
导航视图{
TextField(“名称”,文本:nonNilBinding.Name)
.navigationTitle(“编辑位置”)
.navigationBarItems(尾部:按钮(“完成”){disease()})
}
}
}
您是否尝试过不使用强制换行可选的@State var location:location?
您可能还想要@StateObject
而不是@State
。。。。我第一次读到它们的时候,我认为隐式展开可选的是愚蠢的,但是我比我预期的更早地发现了一个用例,这就是我在这里试图复制的。使用MapKit,我有一个注释(我在这里使用location)。它是隐式展开的,因为当视图加载时,它是零。它只有在创建之后才会被编辑,就像我在这里处理位置一样。调试时,我看到创建了位置,但是,正如您所说,“在设置位置之前呈现工作表。”这就是为什么位置是一个类——它只是我真正想要的东西的替代品,这是一个MKPointAnnotation,是的,这是一个麻烦,使用getter和setter通过扩展和计算属性进行更新。虽然我现在谈论的是可选对象上的可选属性,但这有点不同。隐式展开的选项看起来是一个相当冒险的计划。关于注释,我一直处理这些注释的方法是为地图动态生成它们——而不是保存对它们的引用。
struct Location {
var name : String
}
struct Grandparent: View {
@State var location: Location?
@State var showEditView: Bool = false
var body: some View {
NavigationView {
VStack{
NavigationLink(
destination: Parent(location: $location, showEditView: $showEditView)) {
Text("Navigate")
}
if let location = location {
Text(location.name)
} else {
Text("No location yet")
}
}
.padding()
.sheet(isPresented: $showEditView) {
EditView(placemark: $location, dismiss: { showEditView = false })
}
}
}
}
struct Parent: View {
@Binding var location: Location?
@Binding var showEditView: Bool
var body: some View {
NavigationLink(
destination: Child(location: $location, showEditView: $showEditView),
label: {
Text("Child")
})
}
}
struct Child: View {
@Binding var location: Location?
@Binding var showEditView: Bool
var body: some View {
Button("Make location") {
location = Location(name: "Lebanon")
showEditView = true
}
}
}
struct EditView: View {
@Binding var placemark: Location?
var dismiss: () -> Void
var nonNilBinding : Binding<Location> {
.init { () -> Location in
placemark ?? Location(name:"Default")
} set: { (newValue) in
placemark = newValue
}
}
var body: some View {
NavigationView {
TextField("Name", text: nonNilBinding.name)
.navigationTitle("Edit place")
.navigationBarItems(trailing: Button("Done") { dismiss() })
}
}
}