在我的 init() 方法中调用视图之前,我的 coreData 没有加载
Posted
技术标签:
【中文标题】在我的 init() 方法中调用视图之前,我的 coreData 没有加载【英文标题】:My coreData does not load before the view gets called in my init() method 【发布时间】:2021-04-01 15:00:42 【问题描述】:我正在使用此方法将状态值设置为我的 coreData 实体 UserSettings 中的值,以便我可以将它们显示在屏幕上。
获取 coreData 实体的最常用方法是使用获取请求,但由于某种原因,它没有加载值并说数组为空:
个人资料视图:
import HealthKit
import SwiftUI
import Combine //to use Just
struct ProfileView: View
@Environment(\.managedObjectContext) private var viewContext
@ObservedObject var viewModel: AddViewModel = AddViewModel()
@FetchRequest(
entity: UserSettings.entity(),
sortDescriptors: [])
private var userSettingEntity: FetchedResults<UserSettings>
init()
let x = viewModel.fetchProgresses()
let y = userSettingEntity.count
print(y)
print(x.count)
if(!x.isEmpty)
print(x[0].bmr)
userName = x[0].firstName!
ageInputString = String(x[0].age)
heightInputString = String(x[0].height)
weightInputString = String(x[0].weight)
selectedGender = Double(x[0].age)
chosenActivityLevel = x[0].activityLevel!
BMR = x[0].bmr
var body: some View
VStack //vertical stack for the form
Form
Section
Text(String(BMR))
Any help would be really useful :)
这里是我的视图模型:
class AddViewModel: ObservableObject
@Published var userSettings = [UserSettings]()
init()
// print(fetchProgresses().count)
//Creating the data
func addCalorieTrackerDate(id: UUID, firstName: String, height: Double, weight: Double, gender: String, age: Double, activityLevel: String, bmr: Double)
CoreDataManager.shared.addUserSettingsData(id: id, firstName: firstName, height: height, weight: weight, gender: gender, age: age, activityLevel: activityLevel, bmr: bmr) (isAdded, error) in
if let error = error
print(error)
else
print("Data has been added!")
print(gender)
//fetching the data
func fetchProgresses() -> [UserSettings]
CoreDataManager.shared.fetchCalorieTrackerData (userSettings, error) in
if let error = error
print(error)
if let userSettings = userSettings as? [UserSettings]
self.userSettings = userSettings
return userSettings
CoreDataManager.swift:
class CoreDataManager
static let shared: CoreDataManager =
let appDelegate = AppDelegate.instance!
let instance = CoreDataManager(managedObjectContext: appDelegate.persistanceContainer.viewContext)
return instance
()
var managedContext: NSManagedObjectContext
private init(managedObjectContext: NSManagedObjectContext)
managedContext = managedObjectContext
//MARK:- CalorieTracker Insert/Update/Delete
extension CoreDataManager
func addUserSettingsData(id: UUID, firstName: String, height: Double, weight: Double, gender: String, age: Double, activityLevel: String, bmr: Double, completionHandler: @escaping (_ succeed: Bool, _ error: Error?) -> Void)
let userSettingsEntity = NSEntityDescription.insertNewObject(forEntityName: "UserSettings", into: managedContext) as? UserSettings
userSettingsEntity?.id = id
userSettingsEntity?.firstName = firstName
userSettingsEntity?.height = height
userSettingsEntity?.weight = weight
userSettingsEntity?.gender = gender
userSettingsEntity?.age = age
userSettingsEntity?.activityLevel = activityLevel
userSettingsEntity?.bmr = bmr
do
try managedContext.save()
completionHandler(true, nil)
catch let error
completionHandler(false, error)
func fetchCalorieTrackerData(completionHandler: @escaping (_ succeed: Any?, _ error: Error?) -> Void)
var progresses = [UserSettings]()
let progressRequest: NSFetchRequest<UserSettings> = NSFetchRequest<UserSettings>(entityName: "UserSettings")
do
progresses = try managedContext.fetch(progressRequest)
completionHandler(progresses, nil)
catch let error
completionHandler(nil, error)
func deleteUserSettingData()
let fetchRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "UserSettings")
let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
do
try managedContext.execute(deleteRequest)
catch _ as NSError
【问题讨论】:
不清楚你的视图模型里有什么代码,你的视图里有什么代码。 【参考方案1】:您在不同的地方做类似的事情,所以最好重构它并拥有一个数据源。
在视图模型中更改fetchProgresses
,使其不返回任何内容,因此您将使用已发布的属性userSettings
,而不是从您的视图中。
然后在视图中删除 fetch 请求和 init 内容,并如上所述从视图模型中获取您的数据
struct ProfileView: View
@ObservedObject var viewModel: AddViewModel = AddViewModel()
var body: some View
VStack
Form
Section
Text(String(viewModel.userSettings.first?.bmr ?? 0))
由于您在这里使用的是表单而不是列表,因此您是否总是只在 UserSettings 数组中获得一项?如果是这样,那么您应该在视图模型中通过将发布的属性更改为来解决此问题
@Published var userSettings: UserSettings?
如果你想把它变成更正确的 MVVM 甚至更好,那么在 UserSettings 中为每个属性都有一个已发布的属性
@Published var firstName: String
@Published var bmr: String
...
那么你的视图代码会更简单
【讨论】:
在更改我的 ViewModel 不返回任何内容后,我正在测试您提到的获取值的方式,但是每当我打印(viewModel.userSettings.first.firstName)时它打印为零。而且在文本视图中也不起作用,这很奇怪,因为数据肯定被输入了。 由于某种原因 viewModel.userSettings 总是空的,这很奇怪 您是否对此进行了调试(或添加了打印语句)并逐步通过 fetchCalorieTrackerData 和 fetchProgresses 来验证数据是否正确获取? 奇怪的是,如果我将 viewModel 保留为 [userSettings] 类型,那么您获取值的方法效果很好。如果可行,您会建议使用它吗? '首选的解决方案当然是如果你只有一个对象,但它是你的电话,不使用数组。以上是关于在我的 init() 方法中调用视图之前,我的 coreData 没有加载的主要内容,如果未能解决你的问题,请参考以下文章
为啥在我的视图被推送到导航堆栈之前我的 UIAlertView 没有在屏幕上消失?