Trying to use CoreData
in Keyboard Extension. I guess that database file must be in one place for both - extension and containing app. That place is app group. I made it in Apple account. I set using it in both app and extension (checkbox in Singing and Capabilities). But it s not the same in app and extension or I misunderstood something. Here`s some code.
In my app I made a lazy var to store DB
file URL
in AppDelegate
file:
lazy var secureAppGroupPersistentStoreURL : URL = {
let fileManager = FileManager.default
let groupDirectory = fileManager.containerURL(forSecurityApplicationGroupIdentifier: "group.xxxxx")!
//xxxxx - is my real bundle identificator
return groupDirectory.appendingPathComponent("SharedData.sqlite")
}()
I think it must pointing to file in shared folder. Then I create PersistentContaner
like this
lazy var testPersistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "testDataShare")
let description = NSPersistentStoreDescription(url: secureAppGroupPersistentStoreURL)
description.shouldInferMappingModelAutomatically = true
description.shouldMigrateStoreAutomatically = true
container.persistentStoreDescriptions = [description]
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
I using NSPersistentStoreDescription
to set DB filename. At least I believe it works so:)
After that in my SceneDelegate file I use this container like this (my test entity is called Entity and has only one attribute called name):
//debug
let testContext = (UIApplication.shared.delegate as! AppDelegate).testPersistentContainer.viewContext
let fetchRequest: NSFetchRequest<Entity> = Entity.fetchRequest()
if let keyboards = try? testContext.fetch(fetchRequest){
print("fetch: \(keyboards.debugDescription)")
}else{
print("fetched nothin")
}
let testEntity = Entity(context: testContext)
testEntity.name = "test from app"
_ = try? testContext.save()
just for testing I insert one more object every time I start my app. It works fine for now. I getting debug info in console like this:
fetch: [ (entity: Entity; id: 0x9f53fc35e433bbae ; data: ), (entity: Entity; id: 0x9f53fc35e43fbbae ; data: ), (entity: Entity; id: 0x9f53fc35e43bbbae ; data: ), (entity: Entity; id: 0x9f53fc35e427bbae ; data: ), (entity: Entity; id: 0x9f53fc35e423bbae ; data: ), (entity: Entity; id: 0x9f53fc35e42fbbae ; data: ), (entity: Entity; id: 0x9f53fc35e42bbbae ; data: { name = "test from app"; })]
I did the very same in my extension, added lazy var secureAppGroupPersistentStoreURL
, created PersistentContainer
to KeyboardViewController
and trying to do the same fetch in viewDidLoad()
but its doesn't show any results.
override func viewDidLoad() {
super.viewDidLoad()
let context = self.testPersistentContainer.viewContext
let fetchRequest: NSFetchRequest<Entity> = Entity.fetchRequest()
if let keyboards = try? context.fetch(fetchRequest){
print("fetch: \(keyboards.debugDescription)")
}else{
print("fetched nothin")
}
//...
}
When I starts extension simulation it prints this:
2020-03-06 01:17:25.835412+0300 Keyboard[3482:275851] Failed to inherit CoreMedia permissions from 3042: (null) fetch: []
I expect the objects I saved in app will be able to fetch in extension and vice versa.
What am I doing wrong with database file?