提问人:ChrisH 提问时间:10/15/2023 最后编辑:HangarRashChrisH 更新时间:10/15/2023 访问量:45
CoreData -> 基于某个值的多个数据存储
CoreData -> Multiple data stores based on some value
问:
我有一个奇怪的需求,我怀疑答案将是“它不应该以这种方式工作”,但这里是(不,我还没有尝试过)——我需要能够根据应用程序用户的登录来点击 CoreData 中的各种数据存储。想象一下,一个待命电话被移交给多个人,每个人都有自己的登录名。因此,如果 Bob 拥有手机并登录,它将创建/使用 Bob 独有的 CoreData 数据存储,然后当 Bob 注销并将手机交给 Sandy 时,她会登录并进行相同的交易。
我知道您在 CoreData 初始化代码中提供了 CoreData 数据存储的名称,但我读过许多文章,人们说如果该名称不是应用程序的名称,CoreData 就会变得蠕动。不确定我是否相信这是真的(或者仍然是真的......?),但我只是在这里吠错了树吗?
思潮?
答:
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
酷,我跟着你。非常感谢!如前所述,这是目前的讨论。我知道这是为什么以及如何工作的,它看起来非常可靠。我会将其标记为已接受。谢谢!
评论
userid