如果Core Data count / fetch请求中的实体名称错误,如何避免崩溃?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如果Core Data count / fetch请求中的实体名称错误,如何避免崩溃?相关的知识,希望对你有一定的参考价值。

我正在为所有持久性存储类编写通用基类。每个子类将使用Core Data在持久数据库中使用一个特定实体/表。线程似乎工作正常,我可以正确获取表中的项目数。问题是如果获取请求中的实体名称错误,我没有得到异常,我得到了崩溃。由于这是一个字符串,并且由程序员在代码中的某处键入,我想以更好的方式检测错误,以便程序员被警告使用了无效的实体名称。

这是我的代码:

class Store<EntityType:NSFetchRequestResult> : NSObject {
    private var entityName : String = ""
    init( entityName : String ) {
        self.entityName = entityName
    }

    public var Count : Int
    {
        get {
            var fetchResults : Int = 0
            objc_sync_enter( self )
            do {

                var privateContext : NSManagedObjectContext? = nil
                DispatchQueue.main.sync {
                    let deleg = UIApplication.shared.delegate as! AppDelegate
                    privateContext = deleg.privateManagedObjectContext
                }

                if privateContext == nil
                    { return 0 }

                privateContext!.performAndWait {
                    do
                    {
                        let request = NSFetchRequest<EntityType>( entityName: self.entityName )
                        fetchResults = try privateContext!.count( for: request )
                    } catch
                    {
                        print("Unexpected error: (error).")
                    }
                }
            }
            objc_sync_exit( self )
            return fetchResults
        }
    }
...

使用错误的实体名称,MOC上的count()函数会导致SIGABRT并且不会抛出任何异常。

我怎么能以某种方式捕获错误?

我也对有关线程的评论持开放态度并在后台线程中使用它。它现在有效,但由于互联网和苹果都说有关如何在后台线程中使用核心数据的模糊内容,所以我们非常感谢帮助。

我刚刚尝试过这个:

let request = NSFetchRequest<EntityType>( entityName: String(reflecting: EntityType.self) )

名称采用“app name.entityname”的形式,因此可以使用。但是,由于编辑器允许程序员为实体和类输入不同的名称,因此这根本不安全。如果我可以在运行时以某种方式检查名称是否有效,我将使用此方法。但是如果不解决崩溃问题,我现在不愿意改变任何事情。

答案

可以获取上下文模型中存在的实体名称列表。

这样,您可以在执行获取请求之前检查程序员提供的实体名称是否有效。

//get the context and make sure it's not nil
guard let privateContext = privateContext 
else { 
    print("Unexpected error: context is nil.")
    return 0 
}

//get the names of entities in the model associated with this context
// credit: Snowman, https://stackoverflow.com/questions/5997586/core-data-list-entity-names
guard let names = privateContext.persistentStoreCoordinator?.managedObjectModel.entities.map({ (entity) -> String? in
    return entity.name
}) 
else { 
    print("Unexpected error: Could not get entity names from model.")
    return 0 
}

//make sure the name specified by the programmer exists in the model    
guard names.contains(where: { (name) -> Bool in
    return name == self.entityName
})
else {
    print("Unexpected error: (self.entityName) does not exist in the model.")
    return 0 
}

privateContext.performAndWait {
    do 
    {
        let request = NSFetchRequest<EntityType>( entityName: self.entityName )
        fetchResults = try privateContext.count( for: request )
    } catch
    {
        print("Unexpected error: (error).")
    }
}

如果你想知道性能:在我的测试中,对于具有20个实体的模型,检索实体名称列表500次需要20毫秒。没什么好担心的。

以上是关于如果Core Data count / fetch请求中的实体名称错误,如何避免崩溃?的主要内容,如果未能解决你的问题,请参考以下文章

Core Data Fetch 没有返回它应该返回的对象

iOS Core Data Fetch Request,如何使用

Core Data Freeze at fetch request(死锁)

Core Data Fetch 在插入实体时保存关系(同时)

如何确保从上下文而不是缓存中获取 Core Data Fetched Property?

Core Data Fetch 在第二次使用谓词时返回 0 个结果