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

问题描述 投票:0回答:1

我有一个奇怪的需求,我怀疑答案将是“它不应该那样工作”,但这里是(不,我还没有尝试过)-我需要能够打各种基于应用程序用户的登录数据存储在 CoreData 中。想象一下一个待命电话,它被交给多个人,每个人都有自己的登录信息。因此,如果鲍勃拥有手机并登录,它会创建/使用鲍勃独有的 CoreData 数据存储,然后当鲍勃注销并将手机交给桑迪时,她会登录并进行同样的交易。

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

想法?

ios swift core-data
1个回答
0
投票

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

要实现此目的,您需要创建

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)
    }
}

© www.soinside.com 2019 - 2024. All rights reserved.