1

I have previously created an iOS app that saves data to a database. I have copied data off the app and now have three files:

MyData.sqlite, MyData.sqlite-shm, and MyData.sqlite-wal

I am trying to create a command-line utility in Xcode that will access the data from those databases. I have added CoreData to the command line utility project, and am able to create a new database. What I want though is to load the database I have exported from the app.

I have found a previous question from someone: Migrate Core Data database from one app to another

However, their answer does not work for me. This line:

let storeUrl = FileManager.default.urls(for: .documentDirectory, in:.userDomainMask).first!.appendingPathComponent(databaseName + ".sqlite")

gives this error:

expression produced error: error: /var/folders/cc/r_54b90515v_m6t41vg9lg000000gp/T/expr14-6084fa..swift:1:65: error: use of undeclared type 'Foundation'
Swift._DebuggerSupport.stringForPrintObject(Swift.UnsafePointer<Foundation.URL>(bitPattern: 0x1004fc2f0)!.pointee)

I feel like I must be missing a simple answer to this problem. Is there an easy way to transplant the Core Data database information from one app to another?

EDIT: Thanks to Lou Franco below I have made some progress. I now have:

var persistentContainer: NSPersistentContainer = {

    let container = NSPersistentContainer(name: "MyData")
    let storeUrl = URL(fileURLWithPath: "/Path/To/Data/MyData.sqlite")
    container.persistentStoreDescriptions = [NSPersistentStoreDescription(url: storeUrl)]
    container.loadPersistentStores(completionHandler: { (storeDescription, error) in
        if let error = error as NSError? {

            fatalError("Unresolved error \(error), \(error.userInfo)")
        }
    })
    return container
}()

However I now get a whole bunch of output summarised by "Persistent store migration failed, missing mapping model."

I was hoping by setting the container with the current Core Data initially I could somehow let the program know what to expect of what it is loading (the data model is the same) but it seems to fail regardless. I noticed in the error messages:

NSInferMappingModelAutomaticallyOption = 1;
NSMigratePersistentStoresAutomaticallyOption = 1;

Is there a way of having the program know that the data it is loading conforms to the Core Data model I already set? It just has to load the data from the file.

2 Answers 2

1

This line:

let storeUrl = FileManager.default.urls(for: .documentDirectory, in:.userDomainMask).first!.appendingPathComponent(databaseName + ".sqlite")

Doesn't work for command-line utilities. It's for apps.

You are going to have to get a path some other way (command line arg, hard-code, relative to utility, etc)

For example:

 URL(fileURLWithPath: FileManager.default.currentDirectoryPath).appendingPathComponent("YOURFILE"))
Sign up to request clarification or add additional context in comments.

5 Comments

Thank you, if I have the three relevant files together with the main.swift file in the XCode project is there a simple way to have them be loaded? If I just put the file names it complains that they are strings when they should be paths.
Thank you. However I get the same error from this line: expression produced error: error: /var/folders/cc/r_54b90515v_m6t41vg9lg000000gp/T/expr34-35f709..swift:1:65: error: use of undeclared type 'Foundation' Swift._DebuggerSupport.stringForPrintObject(Swift.UnsafePointer<Foundation.URL>(bitPattern: 0x1004fc2f0)!.pointee)
You need to provide more information. I suggest narrowing it down by commenting out code until you know exactly what is causing it.
Hi Lou, I have made some progress and edited the post above.
Go get the .momd file from your IPA and look at the code here: developer.apple.com/library/archive/documentation/Cocoa/… under "NSPersistentContainer". Rename the IPA to have a .zip extension and then unzip it. In there you will find the .momd file
0

Thanks to some of the recommendations from Lou Franco, I have found my way to a working solution. I grabbed the .momd file from the original app by archiving it and exploring the exported .app file in the .xcarchive. Here is a minimal example that loads data from an existing sqlite database at "/Path/To/Data/MyData.sqlite" using the data model from "/Path/To/Data/MyData.momd". It simply grabs all of the unique session IDs:

import Foundation
import CoreData

let storePath = "/Path/To/Data/MyData.sqlite"
let storeURL = URL(fileURLWithPath: storePath)

let modelPath =  "/Path/To/Data/MyData.momd"
let modelUrl = URL(fileURLWithPath: modelPath)
let mom = NSManagedObjectModel(contentsOf: modelUrl)!

let psc = NSPersistentStoreCoordinator(managedObjectModel: mom)

let managedObjectContext = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.mainQueueConcurrencyType)
managedObjectContext.persistentStoreCoordinator = psc

try psc.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: storeURL, options: nil)

let request: NSFetchRequest<Session> = Session.fetchRequest()
request.sortDescriptors = [NSSortDescriptor(key: "uniqueSessionID", ascending: true)]
let context = managedObjectContext
do {
    let dbReturn = try context.fetch(request)
    print(dbReturn)
}

Comments

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.