如何在类方法中执行 Core Data NSFetchRequest?

Posted

技术标签:

【中文标题】如何在类方法中执行 Core Data NSFetchRequest?【英文标题】:How to execute Core Data NSFetchRequest in a class method? 【发布时间】:2020-06-26 09:07:15 【问题描述】:

我有AppName.xcdatamodeld 文件,CategoryEntities 中。在Category 中,我成功地从 SwiftUI 添加记录并成功地在View 中获取它们,如下所示:

import SwiftUI
import CoreData

struct CategoriesList: View 
    @Environment(\.managedObjectContext) var moc
    
    var fetchRequest: FetchRequest<CountdownCategory>
    var countdownCategories: FetchedResults<CountdownCategory> 
        fetchRequest.wrappedValue
    
    
    var body: some View 
        ForEach(countdownCategories, id: \.self)  countdownCategory in
            Text(countdownCategory.title ?? "Category")
        
    
    
    init() 
        fetchRequest = FetchRequest<CountdownCategory>(entity: CountdownCategory.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \CountdownCategory.dateAdded, ascending: false)])
    

现在我需要在程序的不同位置执行相同的查询 - 不是在 SwiftUI 视图中,而是在类中的方法中:

import Foundation
import CoreData

class Categories 
    func getCategories() 
        let moc = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
        let categoriesFetch = NSFetchRequest<NSFetchRequestResult>(entityName: "CountdownCategory")
         
        do 
            let categoriesFetch = try moc.fetch(categoriesFetch) as! [CountdownCategory]
         catch 
            fatalError("Failed to fetch categories: \(error)")
        
        
        // etc.
    

我在official Core Data documentation 中查找了示例代码,但是当我尝试执行此代码时出现错误:

*** 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“+entityForName:nil 不是用于搜索实体名称“CountdownCategory”的合法 NSPersistentStoreCoordinator”

对于修复该错误的任何帮助将不胜感激。我的目标是通过这种方法从CountdownCategory 获取核心数据中的数据。 (斯威夫特 5.2)

UPD #1:当我使用 let categoriesFetch = CountdownCategory.fetchRequest() 时出现错误:

'fetchRequest()'的模糊使用

UPD #2:当我使用let categoriesFetch: NSFetchRequest&lt;CountdownCategory&gt; = CountdownCategory.fetchRequest() 时,我不会崩溃。但是如何获取数据呢?

【问题讨论】:

【参考方案1】:
let moc = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)

您在这里创建了一个全新的托管对象上下文,没有支持持久存储或模型。这不是正确的做法。无论来自何处,您都需要使用传入 SwiftUI 环境对象的相同上下文。

您说过应用程序委托有一个NSPersistentContainer,所以我猜您使用的是 SwiftUI/Core Data 应用程序模板。在这种情况下,您需要将上面的代码行 (let moc = ...) 替换为以下内容:

let moc = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext

如果您正在使用模板,您可以查看 SceneDelegate.swift 并查看使用类似代码将上下文注入到 SwiftUI 环境中的位置。

【讨论】:

我将环境对象传递给 View,如下所示:CategoriesList().environment(\.managedObjectContext, moc),但我很难在方法中声明/使用它。 您评论中代码中的moc 来自哪里?这就是你需要在类方法中使用的实例 它来自@Environment(\.managedObjectContext) var moc,在var body: some View 之前的一个视图中... 您需要沿着这条链往上走,直到找到它最初的创建位置。您的应用是否在任何地方都有NSPersistentContainer 是的,在核心数据堆栈部分的AppDelegate.swift 中,let container = NSPersistentCloudKitContainer(name: "MyTitle")

以上是关于如何在类方法中执行 Core Data NSFetchRequest?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Selenium 和 Python 在类中执行方法

在Core Data中,如何在swift 4中执行`if exists update else insert`? [复制]

iOS 5 中 Core Data 的奇怪警告

如何在Core Data中存储CLLocationCoordinate2D数组来绘制折线?

如何制作 Core Data 对象图的精确副本?

如何在应用程序处于后台时执行 Core Data 操作