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?