如何解决"Thread 1: Fatal error: No ObservableObject of type,,,"崩溃消息



我是一个完全的编码新手,这是我的第一个项目。我创建了一个应用程序,可以根据胆固醇面板实验室测试的数据确定心血管疾病(CVD(的风险。该应用程序在iPhone XR(画布模拟器(上运行,没有问题。但是,当我在实际的iPhone XR设备上运行该应用程序时,它会崩溃并产生以下消息:

Fatal Error: No ObservableObject of Type Data found. A View.environmentObject(_:) for Data 
may be missing as an ancestor of this view.

这是错误出现的地方:

TextField("", text: $data.name)
.frame(width:350, height: 40)
.padding(.leading)
.background(Color.offWhite)
.foregroundColor(.fblue)
.cornerRadius(5)
.shadow(color: Color.black.opacity(0.4), radius: 5, x: 5, y: 5)
.shadow(color: Color.white.opacity(1.5), radius:5, x: -5, y: -5)
.font(.title)
.keyboardType(.alphabet)        

我已经搜索了堆栈溢出(SO(并尝试了所有推荐的解决方案,但没有一个对我有用。我还在SO之外进行了搜索,并进行了类似的尝试,结果相似。我已经回到SO看看是否有人可以帮助我。基于这项研究,我认为我在使我的 ObservableObject 对整个应用程序"可见"方面遇到了问题,即使我已经精确地遵循了备受尊敬的编码人员和编码大师(SO 贡献者、Paul Hudson、AzamSharp、Maxcodes、Brian Advent、Code with Chris 等(以及他们在构建应用程序期间的类似示例。所以,我的问题要么出在我用来引用 ObservableObject 的代码语法上,要么我把参考代码放在了应用程序中的错误位置,要么我缺少一段代码,在我的任何研究中从未提到过它。

该应用程序由三个用户输入视图组成,使用文本字段,导航视图和导航链接。一个视图显示用户输入的结果,最后一个视图显示CVD的诊断和风险百分比。我自始至终都使用了@EnvironmentObject、ObservableObject、@Published var 和 @State private var。

以下是一些代码详细信息:(仅显示相关代码(

我的场景代表:

import UIKit
import SwiftUI
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene (_: UIScene, WillConnectTo session: UISceneSession, option connectingOptions: 
UIScene.ConnectionOptions) {
//......
//......
let data = Data()
//....
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
// .....
// .....
let contentView = ContentView(
.environmentObject(data)
.environment(.managedObjectContext, context)
// Use a UIHostingController as window root view controller.
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView.environmentObject(data))
self.window = window
window.makeKeyAndVisible()
}
}
func sceneDidDisconnect.......

我在内容视图中的类声明:

class Data: ObservableObject {

@Published var name = ""
@Published var age = ""
@Published var dob = ""
@Published var gender = ""
@Published var fast = ""
@Published var tc = ""
@Published var tg = ""
@Published var hdl = ""
@Published var ldl = ""
@Published var vldl = ""
@Published var apoB = ""
@Published var apoA1 = ""
@Published var apoRatio = ""
}

结果诊断视图中的"我的结果诊断"结构:

struct ResultsDiagnosticsView: View {
init() {
UITableView.appearance().tableFooterView = UIView()
UITableView.appearance().separatorStyle = .none
}

@EnvironmentObject var data: Data
@State private var name = ""
@State private var age = ""
@State private var dob = ""
@State private var selectedGender = ""
@State private var tc = ""
@State private var tg = ""
@State private var hdl = ""
@State private var ldl = ""
@State private var vldl = ""
@State private var apoB = ""
@State private var apoA1 = "" 

var ptDOB: Double{
let patientDOB = Double(data.dob) ?? 0
return patientDOB
}
var ptTC: Double{
let patientTC = Double(data.tc) ?? 0
return patientTC
}
var ptTG: Double{
let patientTG = Double(data.tg) ?? 0
return patientTG
}
var ptHDL: Double{
let patientHDL = Double(data.hdl) ?? 0
return patientHDL
}
var ptLDL: Double{
let patientLDL = Double(data.ldl) ?? 0
return patientLDL
}
var ptVLDL: Double{
let patientVLDL = Double(data.vldl) ?? 0
return patientVLDL
}
var ptAPOB: Double{
let patientAPOB = Double(data.apoB) ?? 0
return patientAPOB
}
var ptAPOA1: Double{
let patientAPOA1 = Double(data.apoA1) ?? 0
return patientAPOA1
}
var ptAPOBA1: Double{
let patientAPOBA1 = ptAPOB/ptAPOA1
return patientAPOBA1
}

我的诊断风险结构诊断风险视图:

struct DiagnosticsRiskView: View {

@EnvironmentObject var data: Data

@State private var name = ""
@State private var age = ""
@State private var dob = ""
@State private var selectedGender = ""
@State private var tc = ""
@State private var tg = ""
@State private var hdl = ""
@State private var ldl = ""
@State private var vldl = ""
@State private var apoB = ""
@State private var apoA1 = ""
var ptDOB: Double{
let patientDOB = Double(data.dob) ?? 0
return patientDOB
}
var ptTC: Double{
let patientTC = Double(data.tc) ?? 0
return patientTC
}
var ptTG: Double{
let patientTG = Double(data.tg) ?? 0
return patientTG
}
var ptHDL: Double{
let patientHDL = Double(data.hdl) ?? 0
return patientHDL
}
var ptLDL: Double{
let patientLDL = Double(data.ldl) ?? 0
return patientLDL
}
var ptVLDL: Double{
let patientVLDL = Double(data.vldl) ?? 0
return patientVLDL
}
var ptAPOB: Double{
let patientAPOB = Double(data.apoB) ?? 0
return patientAPOB
}
var ptAPOA1: Double{
let patientAPOA1 = Double(data.apoA1) ?? 0
return patientAPOA1
}
var ptAPOBA1: Double{
let patientAPOBA1 = ptAPOB/ptAPOA1
return patientAPOBA1
}

func progress() -> Double {
let j = (ptAPOBA1*3.43) - 0.099
let k = (j/(1+j)) * 100
let l = Double(round(10*k)/10)
return l
}
func setProgress()->CGFloat{
let temp = self.progress() / 2
return CGFloat(temp * 0.01)
}

我的导航视图?用于结果诊断的导航链接视图:

NavigationView {
VStack {
List{
Section(header: Text("Demographics").modifier(SectionMod())) {
HStack {
Text("Patient")
.modifier(Label())
Text(data.name)
.modifier(ResultText())
}.modifier(HStackMod())
.padding(.top, 10)
HStack {
HStack{
Text("Gender")
.modifier(Label())
Text(data.gender)
.modifier(ResultText())
}.modifier(HStackMod())
HStack{
Text("Fasting")
.modifier(Label())
Text(data.fast)
.modifier(ResultText())
}.modifier(HStackMod())
}
HStack {
Text("DOB          ")
.modifier(Label())
Text(data.dob)
.modifier(ResultText())
}.modifier(HStackMod())
.padding(.bottom, 10)
}
Section(header: Text("Cholesterol/Triglycerides").modifier(SectionMod())) {
HStack{
Text("Cholesterol")
.modifier(Label())
Spacer()
.frame(width:115)
if ptTC < 200 {
Text("(ptTC, specifier: "%.2f")  N")
.modifier(Normal())
}else{
Text("(ptTC, specifier: "%.2f")  H")
.modifier(Abnormal())
}
}.modifier(HStackMod())
.padding(.top)
HStack{
Text("Triglycerides")
.modifier(Label())
Spacer()
.frame(width:115)
if ptTG < 100 {
Text("(ptTG, specifier: "%.2f")  N")
.modifier(Normal())
}else{
Text("(ptTG, specifier: "%.2f")  H")
.modifier(Abnormal())
}
}.modifier(HStackMod())
.padding(.bottom, 10)
}

Section(header: Text("Lipoproteins").modifier(SectionMod())) {
HStack{
Text("HDL")
.modifier(Label())
Spacer()
if ptHDL >= 50{
Text("(ptHDL, specifier: "%.2f")  N")
.modifier(Normal())
}else{
Text("(ptHDL, specifier: "%.2f")  L")
.modifier(Abnormal())
}
}.modifier(HStackMod())
.padding(.top, 10)
HStack{
Text("LDL")
.modifier(Label())
Spacer()
if ptLDL < 100{
Text("(ptLDL, specifier: "%.2f")  N")
.modifier(Normal())
}else{
Text("(ptLDL, specifier: "%.2f")  H")
.modifier(Abnormal())
}
}.modifier(HStackMod())
HStack{
Text("VLDL")
.modifier(Label())
Spacer()
if ptVLDL <= 30{
Text("(ptVLDL, specifier: "%.2f")  N")
.modifier(Normal())
}else{
Text("(ptVLDL, specifier: "%.2f") H")
.modifier(Abnormal())
}
}.modifier(HStackMod())
.padding(.bottom, 10)
}
Section(header: Text("Apolipoproteins").modifier(SectionMod())) {
HStack{
Text("Apo B")
.modifier(Label())
Spacer()
if ptAPOB < 85 {
Text("(ptAPOB, specifier: "%.2f")  N")
.modifier(Normal())
}else{
Text("(ptAPOB, specifier: "%.2f")  H")
.modifier(Abnormal())
}
}.modifier(HStackMod())
.padding(.top)
HStack {
Text("Apo A1")
.modifier(Label())
Spacer()
if ptAPOA1 >= 135{
Text("(ptAPOA1, specifier: "%.2f")  N")
.modifier(Normal())
}else{
Text("(ptAPOA1, specifier: "%.2f") L")
.modifier(Abnormal())
}
}.modifier(HStackMod())
HStack {
Text("Apo Ratio")
.modifier(Label())
Spacer()
if ptAPOBA1 < 0.63 {
Text("(ptAPOBA1, specifier: "%.2f")  N")
.modifier(Normal())
}else{
Text("(ptAPOBA1, specifier: "%.2f ")  H")
.modifier(Abnormal())
}
}.modifier(HStackMod())
}
}
HStack{
NavigationLink(destination: TCTGView().navigationBarTitle("")
.navigationBarBackButtonHidden(true)
.navigationBarHidden(true)) {
Text("Start Over")
.fontWeight(.bold)
.font(.subheadline)
.padding()
.background(Color.fblue)//
.foregroundColor(.white)
.cornerRadius(10)
.shadow(color: Color.black.opacity(0.4), radius: 5, x: 5, y: 5)
.shadow(color: Color.white.opacity(1.5), radius:5, x: -5, y: -5)
}
NavigationLink(destination: ApolipoproteinsView().navigationBarTitle("")
.navigationBarBackButtonHidden(true)
.navigationBarHidden(true)) {
Text("Back")
.fontWeight(.bold)
.font(.subheadline)
.padding()
.background(Color.fblue)
.foregroundColor(.white)
.cornerRadius(10)
.shadow(color: Color.black.opacity(0.4), radius: 5, x: 5, y: 5)
.shadow(color: Color.white.opacity(1.5), radius:5, x: -5, y: -5)
}
NavigationLink(destination: DiagnosticsRiskView().navigationBarTitle("")
.navigationBarBackButtonHidden(true)
.navigationBarHidden(true)) {
Text("Next")
.fontWeight(.bold)
.font(.subheadline)
.padding()
.background(Color.fblue)
.foregroundColor(.white)
.cornerRadius(10)
.shadow(color: Color.black.opacity(0.4), radius: 5, x: 5, y: 5)
.shadow(color: Color.white.opacity(1.5), radius:5, x: -5, y: -5)
}
}.padding(.bottom, 80)
}
}.edgesIgnoringSafeArea(.top)

如果该应用程序的完整副本会更有帮助,请给我发电子邮件(wcmarrocco@gmail.com(,因为我无法弄清楚如何在此处嵌入我的项目副本。谢谢!

在您的ResultsDiagnosticsView中添加顶部的ObservalObject,然后通过添加...

NavigationLink(destination: TCTGView().environmentObject(self.data)

最新更新