SwiftUI 2.0 iOS 14 按下按钮时删除核心数据实例
SwiftUI 2.0 iOS 14 Core data delete instance on button press
我想弄清楚如何通过调用我的 ViewModel 中的方法来删除核心数据对象的实例。我设法将实例的 ID 获取到我的方法可能只是在语法上挣扎。我正在使用 Xcode 12.3 iOS 14.3,SwiftUI 2.0 不再使用 SceneDelegate 或 AppDelegate
这是我的视图模型的样子:
import SwiftUI
import CoreData
class ViewModel : ObservableObject{
@Environment(\.managedObjectContext) private var viewContext
@FetchRequest(entity: Counter.entity(), sortDescriptors: [
NSSortDescriptor(
keyPath: \Counter.id,
ascending: true),
NSSortDescriptor(
keyPath:\Counter.windowType,
ascending: true )
]) var counters: FetchedResults<Counter>
//.....
以下是我尝试过但出现此错误的方法
+entityForName: nil 不是用于搜索实体名称的合法 NSPersistentStoreCoordinator 'Counter'
在调试器中单步执行代码后,这是我打印出 CounterRequested 时得到的结果
(entity: Counter; predicate: (id == "C4BE9AFF-8A8E-4413-AFA3-AC90850C482E"); sortDescriptors: ((null)); type: NSManagedObjectResultType; )
ID 确实匹配
然后它在 do 块的第一行崩溃
func deleteCounter(id: UUID) {
let counterRequested: NSFetchRequest<Counter> = Counter.fetchRequest()
counterRequested.predicate = NSPredicate(format: "id=%@", id.uuidString)
do {
let savedCounters = try self.viewContext.fetch(counterRequested)
for counter in savedCounters {
self.viewContext.delete(counter)
}
try self.viewContext.save()
} catch {
print(error)
}
}
}
这是我获取 Id 的来源。我可以通过整个柜台吗?不确定在我的柜台视图中引用什么类型?
List {
ForEach(counters, id: \.self){counter in
CounterCell(id: counter.id!, windowType: counter.windowType!, location: counter.location!, pickedImg: counter.pickedImg!, price: counter.price!, qty: counter.qty!, subtotal: counter.subtotal!) .listRowInsets(.init(top: 0,
leading: 0,
bottom: 20,
trailing: 0))
}
这是我想调用删除方法的视图
struct CounterCell: View {
@Environment(\.colorScheme) var colorScheme
@State private var stepperValue = 0
@StateObject var estimatorData = EstimatorViewModel()
var id: UUID = UUID()
var windowType: String = "Window Type"
var location: String = "Location"
var pickedImg: String = "defaultImg"
var price: String = "0.0"
var qty: String = "0"
var subtotal: String = "0.00"
var body: some View {
//.....
}
这是我找到的一个例子:
import Foundation
import UIKit
import CoreData
class DataManager {
static let shared = DataManager(moc: NSManagedObjectContext.current)
var managedContext: NSManagedObjectContext
private init(moc: NSManagedObjectContext) {
self.managedContext = moc
}
// Delete method
// remove birthday
func removeBirthday(id: UUID) {
let fetchRequest: NSFetchRequest<Birthday> = Birthday.fetchRequest()
fetchRequest.predicate = NSPredicate.init(format: "id=%@", id.uuidString)
do {
let bdays = try self.managedContext.fetch(fetchRequest)
for bday in bdays {
self.managedContext.delete(bday)
}
try self.managedContext.save()
} catch {
print(error)
}
}
}
extension NSManagedObjectContext {
static var current: NSManagedObjectContext {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
return appDelegate.persistentContainer.viewContext
}
}
在您的视图模型中创建一个删除给定对象的方法。
类似
func delete(counter: Counter) {
do {
viewContext.delete(counter)
viewContext.save()
} catch {
// handle error
}
}
我会稍微更新视图代码并让 CounterCell 使用计数器 属性
struct CounterCell: View {
@Environment(\.colorScheme) var colorScheme
@State private var stepperValue = 0
@StateObject var estimatorData = EstimatorViewModel()
var counter: Counter
var body: some View {
//.....
并相应地更改 ForEach
List {
ForEach(counters, id: \.self) { counter in
CounterCell(counter: counter)
//...
}
}
在我进行了上述尝试后,我联系了一位高级开发人员,结果证明这是我在我的视图模型中访问 managedObjectContext 的方式。在此过程中,我了解了如何访问在 Persistence 文件中声明的共享 persistenceController,该文件现在包含在 biolerplate SwiftUI Core Data App 中。
这是我的正确方法。
var viewContext: NSManagedObjectContext { PersistenceController.shared.container.viewContext }
这是我的删除方法
func deleteCounter(id: UUID) {
let counterRequested: NSFetchRequest<Counter> = Counter.fetchRequest()
counterRequested.predicate = NSPredicate.init(format: "id=%@", id.uuidString)
do {
let savedCounters = try self.viewContext.fetch(counterRequested)
for counter in savedCounters {
self.viewContext.delete(counter)
}
try self.viewContext.save()
} catch {
print(error)
}
}
重构
func deleteWindow(id: UUID) {
if let counter = existingCounter {
viewContext.delete(counter)
do {
try viewContext.save()
} catch {
print(error)
}
}
}
我想弄清楚如何通过调用我的 ViewModel 中的方法来删除核心数据对象的实例。我设法将实例的 ID 获取到我的方法可能只是在语法上挣扎。我正在使用 Xcode 12.3 iOS 14.3,SwiftUI 2.0 不再使用 SceneDelegate 或 AppDelegate
这是我的视图模型的样子:
import SwiftUI
import CoreData
class ViewModel : ObservableObject{
@Environment(\.managedObjectContext) private var viewContext
@FetchRequest(entity: Counter.entity(), sortDescriptors: [
NSSortDescriptor(
keyPath: \Counter.id,
ascending: true),
NSSortDescriptor(
keyPath:\Counter.windowType,
ascending: true )
]) var counters: FetchedResults<Counter>
//.....
以下是我尝试过但出现此错误的方法
+entityForName: nil 不是用于搜索实体名称的合法 NSPersistentStoreCoordinator 'Counter'
在调试器中单步执行代码后,这是我打印出 CounterRequested 时得到的结果
ID 确实匹配
然后它在 do 块的第一行崩溃
func deleteCounter(id: UUID) {
let counterRequested: NSFetchRequest<Counter> = Counter.fetchRequest()
counterRequested.predicate = NSPredicate(format: "id=%@", id.uuidString)
do {
let savedCounters = try self.viewContext.fetch(counterRequested)
for counter in savedCounters {
self.viewContext.delete(counter)
}
try self.viewContext.save()
} catch {
print(error)
}
}
}
这是我获取 Id 的来源。我可以通过整个柜台吗?不确定在我的柜台视图中引用什么类型?
List {
ForEach(counters, id: \.self){counter in
CounterCell(id: counter.id!, windowType: counter.windowType!, location: counter.location!, pickedImg: counter.pickedImg!, price: counter.price!, qty: counter.qty!, subtotal: counter.subtotal!) .listRowInsets(.init(top: 0,
leading: 0,
bottom: 20,
trailing: 0))
}
这是我想调用删除方法的视图
struct CounterCell: View {
@Environment(\.colorScheme) var colorScheme
@State private var stepperValue = 0
@StateObject var estimatorData = EstimatorViewModel()
var id: UUID = UUID()
var windowType: String = "Window Type"
var location: String = "Location"
var pickedImg: String = "defaultImg"
var price: String = "0.0"
var qty: String = "0"
var subtotal: String = "0.00"
var body: some View {
//.....
}
这是我找到的一个例子:
import Foundation
import UIKit
import CoreData
class DataManager {
static let shared = DataManager(moc: NSManagedObjectContext.current)
var managedContext: NSManagedObjectContext
private init(moc: NSManagedObjectContext) {
self.managedContext = moc
}
// Delete method
// remove birthday
func removeBirthday(id: UUID) {
let fetchRequest: NSFetchRequest<Birthday> = Birthday.fetchRequest()
fetchRequest.predicate = NSPredicate.init(format: "id=%@", id.uuidString)
do {
let bdays = try self.managedContext.fetch(fetchRequest)
for bday in bdays {
self.managedContext.delete(bday)
}
try self.managedContext.save()
} catch {
print(error)
}
}
}
extension NSManagedObjectContext {
static var current: NSManagedObjectContext {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
return appDelegate.persistentContainer.viewContext
}
}
在您的视图模型中创建一个删除给定对象的方法。
类似
func delete(counter: Counter) {
do {
viewContext.delete(counter)
viewContext.save()
} catch {
// handle error
}
}
我会稍微更新视图代码并让 CounterCell 使用计数器 属性
struct CounterCell: View {
@Environment(\.colorScheme) var colorScheme
@State private var stepperValue = 0
@StateObject var estimatorData = EstimatorViewModel()
var counter: Counter
var body: some View {
//.....
并相应地更改 ForEach
List {
ForEach(counters, id: \.self) { counter in
CounterCell(counter: counter)
//...
}
}
在我进行了上述尝试后,我联系了一位高级开发人员,结果证明这是我在我的视图模型中访问 managedObjectContext 的方式。在此过程中,我了解了如何访问在 Persistence 文件中声明的共享 persistenceController,该文件现在包含在 biolerplate SwiftUI Core Data App 中。
这是我的正确方法。
var viewContext: NSManagedObjectContext { PersistenceController.shared.container.viewContext }
这是我的删除方法
func deleteCounter(id: UUID) {
let counterRequested: NSFetchRequest<Counter> = Counter.fetchRequest()
counterRequested.predicate = NSPredicate.init(format: "id=%@", id.uuidString)
do {
let savedCounters = try self.viewContext.fetch(counterRequested)
for counter in savedCounters {
self.viewContext.delete(counter)
}
try self.viewContext.save()
} catch {
print(error)
}
}
重构
func deleteWindow(id: UUID) {
if let counter = existingCounter {
viewContext.delete(counter)
do {
try viewContext.save()
} catch {
print(error)
}
}
}