Date still in Core Data app after I delete the .sqlite files - swift

I have (finally) managed to get prototype app using Core Data to persist to an sqlite file. Quitting and restarting I see the same data. So all seems well.
I want to now start from scratch again so I went to delete the sqlite persisted data. I set up it's location as :
open lazy var applicationDocumentsDirectory: NSURL = {
// The directory the application uses to store the Core Data store file.
let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
return urls[urls.count-1] as NSURL
}()
let url = self.applicationDocumentsDirectory.appendingPathComponent("TrainingDiary.sqlite")
which places the .sqlite files in ~/Library/Containers/uk.me.stevenlord.Core-Data-Binding/Data/Documents
There are four files in there: iChats, TrainingDiary.sqlite, TrainingDiary.sqlite-shm and TrainingDiary.sqlite-wal
I close my app. Delete all there files. When I reopen my app the full Core Data model is still there and when I look back in this directory the files are back.
What am I missing ?
EDIT:
I've figured out whats happening though I still don't quite understand why this is how it works. The above code specifies where the Core Data should be saved:
which places the .sqlite files in
~/Library/Containers/uk.me.stevenlord.Core-Data-Binding/Data/Documents/TrainingDiary.sqlite
This it does however I've now found that the app also saves the following
~/Library/Containers/uk.me.stevenlord.Core-Data-Binding/Data/Library/Application Support/Core Data Binding/Core_Data_Binding.sqlite
My XCode9 project is called "Core Data Binding". If I delete this file and start up my app I get an app with no data as expected.
So the persistent store is not going to where I specified. So still confused.
I'm missing something still. But something different

Related

Cloud Kit - Synching image

I'm currently sharing data between devices using core data and cloud kit.
Currently I have a "Picture" entity which stores the filename, the date it was added and a relation to another entity.
The details in core data successfully syncs, how would I go about syncing the image file.
The file is saved in the documents folder and I can get its file path using
let imagePath = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent(imageName)
Research seems to show I need to use CKAsset to upload/download the file but how do I go about doing this?
Resolved the issue by saving the image as data into core data, can then convert it back to an image when displaying

read/write database path using sqlite.swift

I'm just starting out trying sqlite.swift and databases with swift. I have prepared a database with tables and preloaded with data. I wish to select data and insert data from within the app.
The problem is that I don't understand where (in my project) to put my database.db file in order for the app to find it.
my connection code:
let path = NSSearchPathForDirectoriesInDomains(
.documentDirectory, .userDomainMask, true
).first!
do {
db = try Connection("\(path)/database.db")
} catch {
db = nil
print ("Unable to open database")
}
In terms of where this file should go, I would suggest the “application support directory”. See File System Programming Guide: Where You Should Put Your App’s Files, which says:
Put user data in Documents/. User data generally includes any files you might want to expose to the user—anything you might want the user to create, import, delete or edit. For a drawing app, user data includes any graphic files the user might create. For a text editor, it includes the text files. Video and audio apps may even include files that the user has downloaded to watch or listen to later.
Put app-created support files in the Library/Application support/ directory. In general, this directory includes files that the app uses to run but that should remain hidden from the user. This directory can also include data files, configuration files, templates and modified versions of resources loaded from the app bundle.
Also see the iOS Storage Best Practices video.
The above is for iOS. If inquiring about macOS, see File System Programming Guide: The Library Directory Stores App-Specific Files.
But regardless of the OS, the technique for referencing the application support directory is largely the same:
do {
let fileURL = try FileManager.default
.url(for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
.appendingPathComponent("database.db")
db = try Connection(fileURL.path)
} catch {
db = nil
print("Unable to open database: \(error)")
}

Caching images in Swift?

I'm downloading images and displaying them each time the user visits a particular view. To make it more efficient I want to start caching so instead of fetching from the database the user already has the images downloaded.
From my research I found a bunch of Swift libraries that handle caching for you, such as HanekeSwift, KingFisher, and Nuke. I'm wondering what the difference is between using one of these libraries and just downloading the image to Core Data.
As far as I know, the first time a user downloads the images I can just save them to Core Data and check if they exist by key the next time. Are there any advantages to using one of these libraries instead?
You shouldn't save images to core data. You should save them to files and then if you want you can store the path or file name or other attributes about the image in core data. You can save the images to your apps documents directory for instance with the following code.
let dir = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)[0] as String
if let filePath = dir.stringByAddingPathComponent("filename.png"){
try? UIImagePNGRepresentation(image)?.write(to: URL(fileURLWithPath: filePath))
}
If you want to save to a sub folder just use FileManager to make sure the sub folder has been created and create it if not.

How to find the path of sqlite.sql file and print it?

I know this question already answered before but when I tried to print the path for the sqlite file of my application as below I got the path but could not go to it in finder.
I used below code to get the path
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).last! as String
print(paths)
The path I got is as below:
/var/mobile/Containers/Data/Application/5412CDDE-8D40-46B2-A61D-65065796F7CE/Documents
when I try to copy and paste it in GOTO it can not find it
please advise me
In case you are using NSPersistantContainer, you get the URL(s):
persistentContainer.persistentStoreCoordinator.persistentStores.first!.url!
when I try to copy and paste it in GOTO it can not find it
that path is on the Simulator and not on the local Finder.
Duplicate of: Access files in /var/mobile/Containers/Data/Application without jailbreaking iPhone
or
Duplicate of: How to view the data in sqlite file running in iphone application?
How to find the path of sqlite.sql file and print it?
accessing your sqlite database is described here:
Copy Sqlite DataBase in Swift does not work properly
Use this in your swift class to get the location of sqlite database for your application running in iOS simulator.
let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
print(urls[urls.count-1] as URL)
You will need SQLite database browser to look after the database. We can only locate sqlite database file only for application running in simulator but not in the iPhone directly.

Bundling a Realm with an App section

I am trying to bundle a realm file with my app. I followed steps 1-5, but I am not clear on step 6. It says to copy the file back to the document folder, especially if it will be edited by the users.
Assuming, the copy statement goes inside the AppDelegate (similar to how it is done in the sample migration code), and the file is copied, what will happen the next time the app is launched? will it copy the file again, and overwrite it? Am I missing something?
Do I need to run it once before I ship the app, and then remove the code from the app delegate?
EDIT: this question is regarding realm-swift
If you bundle Realm file with your app it will be stored inside your app's bundle in Resources directory which is not writeable (because of the code signing). So if you want your users be able to change this data you have to copy this file to some directory with write access. Application’s Documents directory seems to be a good choice and it's also a default directory for default Realm.Configuration.
If it's an initial data for your app and you don't want to overwrite it each time your app launches, you can simply check if destination file exists and not copy your initial database in this case.
You can do it like this:
let initialURL = NSBundle.mainBundle().URLForResource("initial", withExtension: "realm")!
let defaultURL = Realm.Configuration.defaultConfiguration.fileURL!
if (!defaultURL.checkResourceIsReachableAndReturnError(nil)) {
do {
try NSFileManager.defaultManager().copyItemAtURL(initialURL, toURL: defaultURL)
} catch {
// Handle error here
}
}
let realm = try! Realm()
Adding to the above answer. Looks like currently the correct version of checking if realm file exists is: defaultURL.checkResourceIsReachable()