【发布时间】:2020-04-21 15:28:08
【问题描述】:
我正在尝试使用 MVVM 做一个相当简单的 View 以成为一个优秀的 ViewModel 公民。然而, 访问 ViewModel 中的 @Enviromnent 核心数据时代码中断。我创建 ViewModel 中的两个函数。一个通过@Environment 和一个访问核心数据 使用旧样式访问核心数据 - 获取对 AppDelegate 的引用并自己做 事物。 OldSchool 方法有效。下面评论2。 @Environment 不会 - 它会破坏 在下面指示的行中出现对我没有帮助的错误。评论 1。 (线程 1:EXC_BAD_INSTRUCTION(代码=EXC_I386_INVOP,子代码=0x0))
现在,如果我采用相同的 @Environment 代码并将其直接放入视图中,它就可以工作。 如果我在视图中的文本中调用破坏 MVVM 的同一行,我会得到 正确的反应。评论2
这是视图:
struct UserUtilities: View {
@Environment(\.managedObjectContext) var managedObjectContext
@FetchRequest(fetchRequest: DermPhoto.getAllDermPhotos()) var dermPhotos: FetchedResults<DermPhoto>
@State private var reminderInterval = 1
@State private var enableReminders = true
@State private var daysSincePhoto: Int = 0
@ObservedObject var userUtilitiesVM = UserUtilitiesViewModel()
var body: some View {
NavigationView {
VStack {
Group { //group 1
Toggle(isOn: $enableReminders) {
Text("Enable Reminders")
}
.padding(EdgeInsets(top: 50, leading: 50, bottom: 0, trailing: 50))
Text("Reminders are" + (enableReminders == true ? " On" : " Off"))
Spacer()
//Comment 3 - this always works
Text("String interpolation of self.dermPhotos.count")
Text("\(self.dermPhotos.count)")
} //group 1
Group { //group 2
Text("It has been " + "\(self.daysSincePhoto) " + (daysSincePhoto == 1 ? "day" : "days") + " since a photo was added.")
.padding(EdgeInsets(top: 0, leading: 50, bottom: 0, trailing: 50))
//options for the sentence above
//\(self.userUtilitiesVM.getTheDateInterval())
//\(self.userUtilitiesVM.getFromEnvironment())
//\(self.userUtilitiesVM.dateInterval)
Spacer()
Stepper("Reminder Interval", value: $reminderInterval, in: 1 ... 30)
.padding(EdgeInsets(top: 0, leading: 50, bottom: 0, trailing: 50))
Text("Reminder Interval is: \(reminderInterval)" + (reminderInterval == 1 ? " day" : " days"))
Spacer()
}//group 2
}
.navigationBarTitle("Reminder Days", displayMode: .inline)
.navigationBarItems(trailing: Button(action: {
print("getting the date interval from the nav button")
//self.daysSincePhoto = self.userUtilitiesVM.getOldSchool()
self.daysSincePhoto = self.userUtilitiesVM.getFromEnvironment()
//self.daysSincePhoto = self.getFromEnvironment()
} , label: { Text("Fetch")
}))
}
}
//this always works
func getFromEnvironment() -> Int {
let numberOfRecords = self.dermPhotos.count
if numberOfRecords > 0 {
let now = Date()
let lastDate = self.dermPhotos.last?.addDate
//ok to bang - addDate is always added to core data
let dateInterval = DateInterval(start: lastDate!, end: now)
let days = Int(dateInterval.duration) / (24 * 3600)
self.daysSincePhoto = days
return days
}
return 0
}
}
这是 ViewModel:
class UserUtilitiesViewModel: ObservableObject {
@Environment(\.managedObjectContext) var managedObjectContext
@FetchRequest(fetchRequest: DermPhoto.getAllDermPhotos()) var dermPhotos: FetchedResults<DermPhoto>
@Published var dateInterval: Int = 50
//Comment 2 this always works
func getOldSchool() -> Int {
let kAppDelegate = UIApplication.shared.delegate as! AppDelegate
let context = kAppDelegate.persistentContainer.viewContext
var resultsDermPhotos : [DermPhoto] = []
let fetchRequest: NSFetchRequest<DermPhoto> = DermPhoto.fetchRequest() as! NSFetchRequest<DermPhoto>
let sortDescriptor = NSSortDescriptor(key: "addDate", ascending: true)
fetchRequest.sortDescriptors = [sortDescriptor]
do {
resultsDermPhotos = try context.fetch(fetchRequest)
} catch {
print("the fetchRequest error is \(error.localizedDescription)")
}
let numberOfRecords = resultsDermPhotos.count
if numberOfRecords > 0 {
let now = Date()
let lastDate = resultsDermPhotos.last?.addDate
//ok to bang this since addDate is always added to core data
let di = DateInterval(start: lastDate!, end: now)
let days = Int(di.duration) / (24 * 3600)
dateInterval = days
return days
}
return 0
}
//this never works
func getFromEnvironment() -> Int {
//Comment 1 - this breaks
let numberOfRecords = self.dermPhotos.count
if numberOfRecords > 0 {
let now = Date()
let lastDate = self.dermPhotos.last?.addDate
//ok to bang this since addDate is always added to core data
let di = DateInterval(start: lastDate!, end: now)
let days = Int(di.duration) / (24 * 3600)
dateInterval = days
return days
}
return 0
}
}
显然我可以使用老派或放弃 ViewModel 的想法,但我想知道如何解决这个问题。任何指导将不胜感激。 Xcode 11.3 (11C29)
【问题讨论】:
标签: xcode core-data swiftui combine