CoreData -> 基于某个值的多个数据存储

CoreData -> Multiple data stores based on some value

提问人:ChrisH 提问时间:10/15/2023 最后编辑:HangarRashChrisH 更新时间:10/15/2023 访问量:45

问:

我有一个奇怪的需求,我怀疑答案将是“它不应该以这种方式工作”,但这里是(不,我还没有尝试过)——我需要能够根据应用程序用户的登录来点击 CoreData 中的各种数据存储。想象一下,一个待命电话被移交给多个人,每个人都有自己的登录名。因此,如果 Bob 拥有手机并登录,它将创建/使用 Bob 独有的 CoreData 数据存储,然后当 Bob 注销并将手机交给 Sandy 时,她会登录并进行相同的交易。

我知道您在 CoreData 初始化代码中提供了 CoreData 数据存储的名称,但我读过许多文章,人们说如果该名称不是应用程序的名称,CoreData 就会变得蠕动。不确定我是否相信这是真的(或者仍然是真的......?),但我只是在这里吠错了树吗?

思潮?

iOS Swift 核心数据

评论

1赞 lorem ipsum 10/15/2023
仍然正确,但您可以更改 url,不理想但可能
1赞 Paulw11 10/15/2023
可以有多个核心数据持久性存储,并指定不同的 URL,但使用单个托管对象模型。您只需要手动设置协调器,而不是依赖协调器。在实体中有一个字段并在查询中使用该字段可能更简单。userid
0赞 ChrisH 10/19/2023
理解了,这就是它目前的工作方式。管理层对每个用户的数据隔离等存在担忧,但坦率地说,对于手机中普通用户下存在的东西,我不确定我是否同意管理层的担忧。非常感谢。

答:

1赞 cgontijo 10/15/2023 #1

核心数据存储的名称不需要与应用的名称匹配。事实上,对于单个应用,可以有多个具有不同名称的数据存储。

为此,您需要创建提供数据存储名称和托管对象模型。NSPersistentContainter

也就是说,您需要 .NSPersistentContainer(name: storeName)NSPersistentContainer(name: storeName, managedObjectModel: managedObjectModel)

具有挑战性的部分是获取当前版本的数据模型,但下面的代码片段将向您展示如何做到这一点:NSManagedObjectModel

Struct PersistenceController {

    let container: NSPersistentContainer
    
    init(userName: String,
         inMemory: Bool = false) {
        
        // Both the store and data model can be any string, for the sake of simplicity lets
        // consider your app's name
        let yourAppName = "YourAppName"
        
        // Append the userName to your data store name
        let storeName = "\(yourAppName)-\(userName)"
        
        // This must be the same name as the data model file in your project.
        // Typically is the same as the app's name
        let dataModelName = yourAppName
        
        // Here you get the managedObjectModel to create the persistent container
        guard let managedObjectModel = NSManagedObjectModel(name: dataModelName) else {
            fatalError("Cannot instantiate NSManagedObjectModel")
        }
        
        // When you create the persistent container specifying the name and the managed object model,
        // you "decouple" the name of the store from the name of the data model:
        container = NSPersistentContainer(name: storeName, managedObjectModel: managedObjectModel)
        
        
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })
        
        // Other code required for creating the persistent container goes here,
        // including the creation of the mainContex and any background context you need.
    }
}

extension NSManagedObjectModel {
    
    convenience init?(name: String) {
        
        let bundle = Bundle.main
        let dataModelFolder = "\(name).momd"  //Assuming your CoreData model is located in your project's roor directory
        
        // You need to read the current model version from the VersionInfo.plist file, located in the datamodel folder
        guard let versionPlistUrl = bundle.url(forResource: "VersionInfo",
                                               withExtension: "plist",
                                               subdirectory: dataModelFolder) else { fatalError("VersionInfo.plist doesn't exist") }
        
        // Here you parse the VersionInfo.plist file to a Dictionary and get the current version name:
        let versionPlist = NSDictionary(contentsOf: versionPlistUrl)
        let currentVersion = versionPlist?.object(forKey: "NSManagedObjectModel_CurrentVersionName") as? String
        
        // You need the current version model URL to instantiate the managed object model:
        guard let currentModelVersionURL = bundle.url(forResource: currentVersion,
                                                      withExtension: "mom",
                                                      subdirectory: dataModelFolder) else { fatalError("Model not found") }
        
        // Initialise the model with the url defined above
        self.init(contentsOf: currentModelVersionURL)
    }
}

评论

0赞 ChrisH 10/19/2023
酷,我跟着你。非常感谢!如前所述,这是目前的讨论。我知道这是为什么以及如何工作的,它看起来非常可靠。我会将其标记为已接受。谢谢!