首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何判断我的NSManagedObject是否驻留在只读NSPersistentStore中?

如何判断我的NSManagedObject是否驻留在只读NSPersistentStore中?
EN

Stack Overflow用户
提问于 2020-02-28 00:58:07
回答 1查看 64关注 0票数 1

我想将只读示例/教程数据添加到基于核心数据的macOS应用程序中。

我将在我的应用程序包中包含一个包含示例数据的SQL文件。我的NSPersistentContainer有2个NSPersistentStores,一个是可写的,一个是只读的。我将只有我的模型的默认配置,因为两个商店将具有相同的模型。

我的UI需要知道显示的数据是否是只读的,例如,要停止拖动此数据。

我知道NSManagedObject不支持只读状态,请参阅和:Is it possible to return NSManagedObjects as read-only in Core Data? ...and文档。

我认为最好的方法是向我的NSManagedObject派生类添加一个readonly属性,它可以在必要时进行查询。但是,我不明白如何轻松地设置此属性!我找不到从NSManagedObject到NSPersistentStore的直接链接。

我可以设置一个NSFetchRequest并指定只读存储,看看NSManagedObject是否在其中,但这似乎有点荒谬。

我是不是漏掉了什么更明显的东西?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-03-03 18:37:19

感谢pbasdf的建议...

我找不到直接的方法来实现这一点。我不得不放弃使用NSPersistentContainer来简化我的核心数据堆栈。然而,如果你需要你的图的一小部分是只读的,我认为这是一个相当优雅的解决方案。

我对NSPersistentStoreCoordinator进行了子类化,以缓存添加到其中的任何只读存储的NSManagedObjectIDs

代码语言:javascript
复制
class GraphStoreCoordinator: NSPersistentStoreCoordinator
{
    override init(managedObjectModel model: NSManagedObjectModel)
    {
        readOnlyTestContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
        super.init(managedObjectModel: model)
        readOnlyTestContext.persistentStoreCoordinator = self

        NotificationCenter.default
            .addObserver(forName: .NSPersistentStoreCoordinatorStoresDidChange,
                         object: self, queue: nil)  { [unowned self] notification in

            // userInfo will be in this form for add/remove keys - not supporting migration here
            guard let userInfo = notification.userInfo as? [String: [NSPersistentStore]] else {
                unhandledError("Invalid userInfo for NSPersistentStoreCoordinatorStoresDidChange.") }

            userInfo[NSAddedPersistentStoresKey]?.forEach { self.didAddStore($0) }
            userInfo[NSRemovedPersistentStoresKey]?.forEach { self.didRemoveStore($0) }
        }
    }

    deinit {
        NotificationCenter.default
            .removeObserver(self, name: .NSPersistentStoreCoordinatorStoresDidChange, object: self)
    }

    private func didAddStore(_ store: NSPersistentStore) {
        guard store.isReadOnly else { return }

        var addedObjects = Set<NSManagedObjectID>()
        baseEntityNames.forEach { entityName in
            let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: entityName)
            fetchRequest.affectedStores = [store]

            do {
                let addedEntityObjects = try readOnlyTestContext.fetch(fetchRequest)
                addedObjects = addedObjects.union(addedEntityObjects.map { $0.objectID })
            } catch {
                unhandledError("Failed to fetch all \(entityName) for read only check: \(error)") }
        }

        readOnlyObjects[store.identifier] = addedObjects
    }

    private func didRemoveStore(_ store: NSPersistentStore) {
        guard store.isReadOnly else { return }
        readOnlyObjects.removeValue(forKey: store.identifier)
    }

    /// Returns the minimum set of entities that can be fetched for readonly checking
    private lazy var baseEntityNames: [String] = {
        return managedObjectModel.entitiesByName.compactMap { $1.superentity == nil ? $0 : nil }
    }()

    private var readOnlyTestContext: NSManagedObjectContext

    /// Readonly objectIDs keyed per persistent store
    private var readOnlyObjects = [String : Set<NSManagedObjectID>]()

    internal func isObjectReadOnly(_ objectID: NSManagedObjectID) -> Bool {
        return readOnlyObjects.contains(where: { $1.contains(objectID) } )
    }
}

然后,我向NSManagedObject添加了一个扩展,用于查询其NSPersistentStoreCoordinator的只读状态:

代码语言:javascript
复制
public extension NSManagedObject
{
    /// Does this managed object reside in a read-only persistent store?
    var isReadOnly: Bool {
        guard let coordinator = managedObjectContext?
            .persistentStoreCoordinator as? GraphStoreCoordinator else {
            unhandledError("Should only check readonly status in a GraphStoreCoordinator") }

        return coordinator.isObjectReadOnly(objectID)
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60438261

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档