我是编码的新手,这是我的第一个项目。我创建了一个应用程序,它根据胆固醇面板实验室测试的数据确定心血管疾病 (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)
我搜索了 Stack Overflow (SO) 并尝试了所有推荐的解决方案,但没有一个对我有用。我还在 SO 之外进行了搜索,并进行了类似的尝试,得到了类似的结果。我已经回到 SO 看看是否有人可以帮助我。基于这项研究,我认为我在让我的 ObservableObject 对整个应用程序“可见”时遇到了问题,尽管我已经精确地遵循了备受尊敬的编码人员和编码专家(SO 贡献者,Paul Hudson,AzamSharp,Maxcodes,Brian Advent, Code with Chris 等;) 以及他们在构建我的应用程序期间的类似示例。所以,我的问题要么是我用来引用 ObservableObject 的代码的语法,要么是我将该引用代码放在应用程序中的错误位置,或者我缺少一段代码,
该应用程序由三个使用 TextFields、NavViews 和 NavLinks 的用户输入视图组成。一个显示用户输入结果的视图,以及一个显示诊断和 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.......
我在 ContentView 中的类声明:
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 = ""
}
我在 ResultsDiagnosticsView 中的 ResultsDiagnostics 结构:
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
}
我的 DiagnosticsRisk stuct DiagnosticsRiskView:
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)
}
我的导航视图?用于 ResultsDiagnosticsView 的导航链接:
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),因为我不知道如何在此处嵌入我的项目副本。谢谢!