iOS App groups - shared CoreData fails to open - ios

I have an app with a CoreData database and access it using UIManagedDocument.
To share the data with the Watchkit app, I'm moving the database to a shared App Group.
The store is created correctly it seems, but after that it often becomes impossible to access it: the UIManagedDocument keeps trying to reconfigure the store, and NSFileManager doesn't find the file (with fileExistsAtPath).
The problem is in the database location - if I save it in the documents directory instead of the shared Group, it works without trouble. It's also not a problem of accessing it from both apps, even if I don't open the watch app at all the problem appears. The group is also working correctly for sharing NSUserDefaults.
Did anyone see similar problems? Is there any locking mechanism that I need to deal with in a specific way?
Any help will be greatly appreciated, I've been struggling a lot with this issue!

After a lot of searching, I found that the storeURL would change (randomly) between these two:
file:///var/mobile/...
file:///private/var/mobile/...
I used URLByResolvingSymlinksInPath on the URL as specified in the following answer, and incredibly, it fixed it:
What does the /private prefix on an iOS file path indicate?
I'm assuming this is a system bug with the App Group paths... it seems that the different paths were causing the persistentStoreCoordinator to try to reopen the store when it was already open.

Related

MagicalRecord SQLite file empty

I am having problem reading a file. I'm using MagicalRecord as my CoreData wrapper. I successfully save or update object. With my NSLog I can see it, everything is fine and I can use it in my database. But every time I want to see SQLite file with my application (I'm using Datum LE), file is empty. I cannot access that file directly within my Library folder in my app. I copy that file to my desktop and it is empty. What am I doing wrong? So once more, everything inside my iOS application works fine, I can see records being saved and I can fetch them normally.
You are clearly looking at the wrong file. If your app is saving (I assume, across app restarts), the date is definitely saved.
One way to find out is to NSLog the persistent store URL and check the referenced file.
I believe the issue you are encountering is the new default journaling mode that Core Data uses.
See this article
https://developer.apple.com/library/ios/qa/qa1809/_index.html
Basically your changes are not written to the .sqlite file, but are found in .sqlite-wal. HOWEVER, most SQLite reading apps I have tried blow away the -wal when you open the .sqlite, so good luck.
You could try changing the journaling mode for debugging purposes

Putting App Resources in Document Directory in iOS

My app have too much dynamic app resources like images, html+css and xml or json files..that can be updated, So I cannot put these resources in app bundle it will not get updated once on app store i need to have it updated there...secondly i also cannot put these resources on server where I can request the content from server every time i need it...
So my question is that is good to store data locally in document directory??? how does apple app review team will react to it? I have heard that there is an iCloud problem while putting data in document directory is it right?
So where to store data of iOS application locally on device?
Thanks in Advance.... Looking for some good solid answer!
This kind of data should be copied to ~/Library/Application Support. See the File System Programming Guide for full details on where everything goes and how it will be treated.
You may want to consider having the initial assets you are referring to be resident in your application bundle. And then when you have updated versions, save them in your Documents directory (or any legal path you want).
The reason for this is for failover, in case there is a problem, it allows you to revert back. When you are dynamically loading content, you have to factor in you can encounter various problems during a download such as corrupt data or even a dependency not being downloaded yet.
FWIW, I implemented this for a game that supported dynamic loading of content. The bundle had the original assets. There was a temp download directory. When data was validated, it was moved to a locale where it was consumable. On app start, the first step was to just copy the data from the bundle to the consumable directory. While it seems perhaps wasteful and several steps, it worked surprising well and most would not even know this sort of thing was happening.

Updating an iOS app on the AppStore which uses CoreData

I know there are similar questions on this subject but nothing that quite answers my query. I am aware that it is a bit of a newbie question!
I have an app on the AppStore which I will soon be looking to update. My binary contains a pre-loaded sqlite file with a list of data which the user starts off with. However, the user will extensively edit this information and it is crucial that that data is maintained through the update.
I am not changing the CoreData structure at all so won't be performing any migration but my concern is that when I upload the new binary the packaged sqlite file will overwrite the users existing data. I suspect that won't be the case but can anyone shed any light on it?
When updating an application the documents directory is untouched. Presumably your startup code checks to see if you have already copied the initial database from the bundle to the documents directory - this will work the same way after an upgrade.
You are testing this every time you run a new build on your device during development anyway - you've put a whole new version of the app bundle on there, and it doesn't kill all your data, does it? (does it???)

Shipping an iOS app with a read-write enabled (also pre-filled) sqlite database

This is the first time I'm developing for iOS. I need my app to ship with a pre-filled sqlite database which a user will read from and write to. How should I go about deploying this? Can experienced developers help me?
What I thought was this:
I create and pre-fill the database in my development machine, add it to my app bundle. During app initialization in device, I check if I have a database in NSDocumentDirectory of my app. If not, I copy the database in the bundle to NSDocumentDirecory and read from/write into it. If I have a db there, I just use it.
Is this a bad idea? Any pitfalls I'm falling in here?
I have an app that does something pretty similar to that. Mine doesn't allow writing to the database, but I don't see why it would be hard.
I have a dataset that I import into a SQLite database, copy it into the apps directory, put the DB filename into a constant and it seems to work really well.
I change the SQLite filename each time I put it in there (MyDB62020111.sqlite -> MyDB62020112.sqlite) just to make sure that I avoid a problem where it thinks that the file is already in the NSDocumentDirectory and not update it.

How can I ship my app with a pre-populated Core Data database?

My app uses Core Data and I want some default entries to be inside.
What's best practices of how to do that?
If you're already loading the pre-load data via a temporary routine for testing in your current code there's no reason you can't use the sqlite file it creates in the simulator's directory (no need to write a separate Mac app).
If you're not already filling that db you can still write an iOS app that does it. Odds are you've already written the methods for adding data to your store so you can use them to import the pre-load data as well.
Either way you'd grab the sqlite file from the simulator's directory and add it to your app's bundle; on first launch you'll copy it into the appropriate place in the app's directory before pointing Core Data to it. If it's really large the downside is that there will be a copy in the bundle and another on disk, but there's not much you can do about that other than grabbing the data over the network.
As others have suggested, if the amount of data is small you can just import it at first launch, using the methods you've already written for adding data as part of the normal app's workflow.
See the CoreDataBooks example, which has sample code for copying a database at first launch.
EDIT: I've created a Core Data framework (read about it here: http://bikepress.org/?p=1120) that includes this feature.
I would just create a database and put add it to my target so that Xcode copies it into the app bundle. At the first launch just copy it from the app bundle to eg. the documents directory or wherever your app expects the database.
There is Core Data Editor at the app store. Alternatively you could build your own simple mac app just for this particular DB and manage it from there. If the amount of default entries is small, then you're better off storing it in a plist or something and loading it into DB after the first launch.
In iOS 5, my app was rejected if I put a database file into resource bundle. So, I have to download the database from internet instead.

Resources