状态变量定义后如何以编程方式Push新视图?规避项目实体未定义报错
解决方案
你当前写法的核心问题是预先初始化了一个可能无效的Project实例,NavigationLink在页面首次渲染时就会提前构造目标视图,此时用的是未经过Project.create生成的无效实例,很容易触发报错。有两种成熟方案可以解决这个问题:
方案1:使用NavigationLink(item:destination:)(推荐,兼容iOS 15+)
这个API会自动绑定可选类型的状态,仅当可选值不为空时才触发跳转,且构造目标视图时传入的是已确认非空的实例,不需要单独维护跳转状态布尔变量:
struct FirstView: View { // 改成可选类型,不需要默认初始化 @State var newProject: Project? // 不需要单独维护pushNewProject变量 var body: some View { // ... 原有视图代码 .toolbar{ ToolbarItem(placement: .navigationBarTrailing){ Button(action: { // 创建完直接给可选变量赋值即可,会自动触发跳转 self.newProject = Project.create(context: viewContext) }){ Text("Create Project") } } } // 用可选绑定的NavigationLink NavigationLink(item: $newProject) { project in // 这里传入的project是自动解包的非空实例,不会有未定义问题 ProjectSideBar(project: project) } label: { EmptyView() }.hidden() } }
方案2:兼容低版本iOS的isActive写法
如果需要支持iOS 15以下的系统,继续用isActive绑定的话,只要把参数改为可选类型,在构造目标视图时做非空判断即可:
struct FirstView: View { @State var newProject: Project? @State var pushNewProject:Bool = false var body: some View { // ... 原有视图代码 .toolbar{ ToolbarItem(placement: .navigationBarTrailing){ Button(action: { self.newProject = Project.create(context: viewContext) self.pushNewProject = true }){ Text("Create Project") } } } NavigationLink(isActive: $pushNewProject) { // 非空判断避免传入未定义的实例,跳转逻辑保证这里必然能解包成功 if let project = newProject { ProjectSideBar(project: project) } else { EmptyView() } } label: { EmptyView() }.hidden() } }
注意:不要用强制解包
!处理可选值,避免极端场景下的闪退问题,上述两种方案都可以完全避免项目实体未定义的报错。
内容的提问来源于stack exchange,提问作者scientiffic
相关产品推荐
相关产品推荐

