2

First time SO user so excited to be here.

I've come up against a problem where I am trying to access my Core Data model in both main app and app extension, call directory. I've followed many online suggestions however none have seemed to work.

I've got the Call Directory Extension work and being able to reload from main app. Print in beginRequest confirms this.

I've then created a new Data model, CallerData with an entity Caller with a single attribute number.

I've also registered an app group in Apple developer and added the group in both targets. Everything is green.

I've then got my AppDelegate persistent container as:

lazy var persistentContainer: NSPersistentContainer = {
        let container = NSPersistentContainer(name: "CallerData")
        let storeURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.io.project.ios.core.data")!.appendingPathComponent("CallerData.sqlite")

        var defaultURL: URL?
        if let storeDescription = container.persistentStoreDescriptions.first, let url = storeDescription.url {
            defaultURL = FileManager.default.fileExists(atPath: url.path) ? url : nil
        }

        if defaultURL == nil {
            container.persistentStoreDescriptions = [NSPersistentStoreDescription(url: storeURL)]
        }
        container.loadPersistentStores(completionHandler: { [unowned container] (storeDescription, error) in
            if let error = error as NSError? {
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }

            if let url = defaultURL, url.absoluteString != storeURL.absoluteString {
                let coordinator = container.persistentStoreCoordinator
                if let oldStore = coordinator.persistentStore(for: url) {
                    do {
                        try coordinator.migratePersistentStore(oldStore, to: storeURL, options: nil, withType: NSSQLiteStoreType)
                    } catch {
                        print(error.localizedDescription)
                    }

                    // delete old store
                    let fileCoordinator = NSFileCoordinator(filePresenter: nil)
                    fileCoordinator.coordinate(writingItemAt: url, options: .forDeleting, error: nil, byAccessor: { url in
                        do {
                            try FileManager.default.removeItem(at: url)
                        } catch {
                            print(error.localizedDescription)
                        }
                    })
                }
            }
        })
        return container
    }()

I've added Core Data to both targets and I've been able to successfully write and retrieve from the data store in my main app view controller using:

Save core data

if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
            let context = appDelegate.persistentContainer.viewContext

            guard let entityDescription = NSEntityDescription.entity(forEntityName: "Caller", in: context) else { return }

            let newValue = NSManagedObject(entity: entityDescription, insertInto: context)
            newValue.setValue(number, forKey: "number")

            do {
                try context.save()
                print("Saved \(number)")

            } catch {
                print("Saving error")
            }
        }
Retrieve

if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
            let context = appDelegate.persistentContainer.viewContext

            let fetchRequest = NSFetchRequest<Caller>(entityName: "Caller")

            let numberSort = NSSortDescriptor(key:"number", ascending:true)
            fetchRequest.sortDescriptors = [numberSort]

            do {
                let results = try context.fetch(fetchRequest)

                for result in results {
                    print("Block core data result \(result.number)")
                }

            } catch {
                print("Could not retrieve")
            }
        }

Now when I try to fetch the data from my app extension I get many errors. Below is the extension code and the errors.

lazy var persistentContainer: NSPersistentContainer = {
            let container = NSPersistentContainer(name: "CallerData")
            let storeURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.io.project.core.data")!.appendingPathComponent("CallerData.sqlite")

            var defaultURL: URL?
            if let storeDescription = container.persistentStoreDescriptions.first, let url = storeDescription.url {
                defaultURL = FileManager.default.fileExists(atPath: url.path) ? url : nil
            }

            if defaultURL == nil {
                container.persistentStoreDescriptions = [NSPersistentStoreDescription(url: storeURL)]
            }
            container.loadPersistentStores(completionHandler: { [unowned container] (storeDescription, error) in
                if let error = error as NSError? {
                    fatalError("Unresolved error \(error), \(error.userInfo)")
                }

                if let url = defaultURL, url.absoluteString != storeURL.absoluteString {
                    let coordinator = container.persistentStoreCoordinator
                    if let oldStore = coordinator.persistentStore(for: url) {
                        do {
                            try coordinator.migratePersistentStore(oldStore, to: storeURL, options: nil, withType: NSSQLiteStoreType)
                        } catch {
                            print(error.localizedDescription)
                        }

                        // delete old store
                        let fileCoordinator = NSFileCoordinator(filePresenter: nil)
                        fileCoordinator.coordinate(writingItemAt: url, options: .forDeleting, error: nil, byAccessor: { url in
                            do {
                                try FileManager.default.removeItem(at: url)
                            } catch {
                                print(error.localizedDescription)
                            }
                        })
                    }
                }
            })
            return container
        }()
        
        
        let dataContext = persistentContainer.viewContext
        let fetchRequest = NSFetchRequest<Caller>(entityName: "Caller")

        let numberSort = NSSortDescriptor(key:"number", ascending:true)
        fetchRequest.sortDescriptors = [numberSort]

        do {
            let results = try dataContext.fetch(fetchRequest)

            for result in results {
                print("Block core data result from Call Directory Extension \(result.number)")
            }

        } catch {
            print("Could not retrieve")
        }
[error] error: addPersistentStoreWithType:configuration:URL:options:error: returned error NSCocoaErrorDomain (256)
CoreData: annotation:   NSSQLiteErrorDomain : 14
CoreData: annotation: storeType: SQLite
CoreData: annotation: configuration: PF_DEFAULT_CONFIGURATION_NAME
CoreData: annotation: URL: file:///private/var/mobile/Containers/Shared/AppGroup/70930707-4B5E-46E8-9083-C0D446A5568D/CallerData.sqlite/
CoreData: annotation: options:
CoreData: annotation:   NSPersistentStoreRemoveUbiquitousMetadataOption : 1
The file “CallerData.sqlite” couldn’t be opened.

Any help is appreciated.

Thanks

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.