Dealing with Managed Objects between two MVC's with one database - ios

Current Setup:
MVC-1, onViewDidLoad, creates a Managed Object, fetches data from the Managed Object and updates various UI elements.
MVC-2: Same exact setup. I copied and pasted the same code from MVC-1 into MVC-2.
Issues I am seeing:
After launch and opening MVC-1, all the code is executed without any errors. The ManagedObject is created, the fetch requests on the ManageObjectContext work and the UI is properly updated. However, when switching to MVC-2 it seems that none of the data, that MVC-2 is suppose to fetch, is actually being updated. All the UI Elements in MVC-2 have the same data from the last time the application was launched.
Furthermore, if I launch the application and open MVC-2 first I get the same results, only MVC-1 does not appear to be updated this time around.
What is it that I am over looking? I have explicit saves to the database being made. I am (at least I think I am) creating two different ManagedObjects. Do I need to somehow close one before creating the other? Any advice would be very helpful. Thanks.

Figured it out.
I was saving the MOC, however I was not writing the NSManagedDocument to disk (I am using a ManagedDocument as a container for the Core Data database).
So naturally, when I switched to the MVC-2 I would not have the updated data.
I now save the MOC, write the MD to disk and close the MD at viewWillDisappear.
Thanks for the help gusy.

Related

CoreData iCloud changes not saved

I m making an app with CoreData and iCloud integration. I went through the Apple Documentation to adapt my already working app to integrate iCloud synchronization.
Inserting objects and deleting seems to be working fine. When I delete the app and reinstall it on my phone all synchronized data are correctly restored.
My issue is when I modify an NSManagedObject. The context which I used to query CoreData to fetch my object does not detect any changes on my objects when I modify a field. Therefore the context is not saved. If I try to force saving context even when no changes are detected, nothing is saved.
I went through stack oververflow and found that the context must have a stalenessInterval set to 0.0. This did nothing to my app. Do you have any idea on what could be wrong ?
I noticed that the context carried by the NSManagedObject seems different than the one I used to fetch data. If I call save method on this context, nothing happened either.
I am completely lost, since I thought it would ba as easy as inserting and deleting objects.
Thanks for your help !
(ps: I code with Swift but even Objective C code is acceptable as answer :) )
I was actually trying to use two databases whereas I should have used configurations to separate entities saved to the cloud and those saved locally.
For those who wants more information on CoreData with iCloud i suggest to go through this video from Apple WWDC 2012 which helps a lot getting into this subject.

Core Data doesn't save the first time

I have a problem with RestKit 0.22 and Core Data for saving. To be sure that the rest of my project doesn't cause the problem, I reproduce it with RKTwitterCoreData in RestKit examples. I simply remove seeding part to start with an empty sqlite database. My app is based on the same concept.
My problem happens the first time I run the app. The app receives the data from twitter and displays it. But if I look at the sqlite database itself, it's empty. When I start the app the second time, the database is filling.
Is it possible for RestKit to save the data at the moment it receives it?
Is it possible that RestKit cache all data before saving them. I though that my problem happened because managedObjectCache in RKManagedObjectStore is set with RKInMemoryManagedObjectCache but I also tried with RKFetchRequestManagedObjectCache and I got the same result.
I also tried to save manually in the success bloc with [[[RKManagedObjectStore defaultStore] persistentStoreManagedObjectContext] save:nil] and that didn't work.
Thank you
RestKit does save the mapping result automatically, and before calling the success completion block.
If you want to check what is in the store, ask the MOC (main thread or persistent store MOC) and check the registeredObjects / run a fetch request.
You should not look at the SQLite file(s). The table structure is a private implementation detail, and if you load the file at the command line with the wrong options you won't necessarily see what you expect.

From UIManagedDocument to traditional Core Data stack

I created a new App using UIManagedDocument. While on my devices everything is fine, I got a lot of bad ratings, because there are problems on other devices :(
After a lot of reading and testing, I decided to go back to the traditional Core Data stack.
But what is the best way to do this with an app, that is already in the app store?
How can I build this update? What should I take care of?
Thanks,
Stefan
I think you may be better off to determine your issues with UIManagedDocument and resolve them.
However, if you want to go to plain MOC, you only have a few things to worry about. The biggest is that the UIMD stores things in a file package, and depending on your options you may have to worry about change logs.
In the end, if you want a single sqlite file, and you want to reduce the possibility of confusion, you have a class that simply opens your UIManagedDocument, and fetches each object, then replicates it in the single sqlite file for your new MOC.
Now, you should not need a different object model, so you should not have any migration issues.
Then, just delete the file package that holds the UIManagedDocument, and only use your single file sqlite store.
Basically, on startup, you try to open the UIManagedDocument. If it opens, load every object and copy it into the new database. Then delete it.
From then, you should be good to go.
Note, however, that you may now experience some UI delays because all the database IO is happening on the main UI thread. To work around this, you may need to use a separate MOC, and coordinate changes via the normal COreData notification mechanisms. There are tons of documents, examples, and tutorials on that.
EDIT
Thanks for your answer. My problem with these issues is, that I'm not
able to reproduce them. All my Devices are working fine. But I got a
lot mails, about problems like this: - duplicate entries - no data
after stoping and restarting the app - some say, that the app works
fine for some days and stops working(no new data). These are all
strange things, that don't happen on my devices. So for me the best
way is to go back to plain MOC. My DB doesn't hold many user generated
data, all the data is loaded from a webservice, so it's no problem to
delete the data and start of using a new DB. – Urkman
Duplicate entries. That one sounds like the bug related to temporary/permanent IDs. There are lots of posts about that. Here is one: Core Data could not fullfil fault for object after obtainPermanantIDs
Not saving. Sounds like you are not using the right API for UIManagedDocument. You need to make sure to not save the MOC directly, and either use an undo manager or call updateChangeCount: to notify UIManagedDocument that it has dirty data that you want to be saved. Again, lots of posts about that as well. Search for updateChangeCount.
However, you know your app best, and it may just be better and easier to use plain Core Data.
Remember, if you are doing lots of imports from the web, to use a separate MOC, and have your main MOC watch for DidSave notifications to update itself with the newly imported data.
UIManagedDocument is a special kind of document, an UIDocument subclass, that stores its data using Core Data Framework. So it combines the power of document architecture and core data capabilities.
You can read more about document based architecture from Document Based App Programming Guide for iOS and I recommend WWDC2011 Storing Documents in iCloud using iOS5 session video. I also recommend Stanford CS193P: iPad and iPhone App Development (Fall 2011) Lecture 13.
What is created when you call saveToURL:forSaveOperation:completionHandler: is an implementation detail of UIManagedDocument and UIDocument and you should not really worry or depend on it. However in current implementation a folder containing an sqlite database file is being created.
No. All entities will be contained in a single database file also more generally called: a persistent store. It is possible to use more than one persistent store, but those are more advanced use cases and UIManagedDocument currently uses one.
UIManagedDocument's context refers to a NSManagedObjectContext from underlying Core Data Framework. UIManagedDocument actually operates two of those in parallel to spin off IO operations to a background thread. When it comes to the nature of a context itself here's a quote from Core Data Programming Guide:
You can think of a managed object context as an intelligent scratch pad. When you fetch objects from a persistent store, you bring temporary copies onto the scratch pad where they form an object graph (or a collection of object graphs). You can then modify those objects however you like. Unless you actually save those changes, however, the persistent store remains unaltered.
But it really is a good idea to take a look at the lectures and other material I posted above to get a general picture of the technologies used and their potential value to you as a developer in different situations.

Optimal way of syncing Core Data with server-side data?

I have what I would presume is a very common situation, but as I'm new to iOS programming, I'm not sure of the optimal way to code it.
Synopsis:
I have data on a server which can be retrieved by the iPhone app via a REST service. On the server side, the data is objects with a foreign key (an integer id number).
I'm storing the data retrieved via REST in Core Data. The managed objects have an "objId" attribute so that I can uniquely identify the managed objects in the rest of my code.
My app must always reflect the server data.
On subsequent requests made to the server:
some objects may not be returned, they have been deleted on the server - in which case I need to delete the corresponding objects from Core Data - so that I'm reflecting the state of the server correctly.
some objects have attributes which have changed, therefore the corresponding managed objects need updating with the new data.
my solution - and question to you
To get things going in my app, I made the easiest solution of deleting all objects in Core Data, then adding all new objects in, created with the latest server side data.
I don't think this is the best way to approach it :) As I progress on with my app, I now want to link up my tableview with NSFetchedResultsController, and have realised that my approach of deleting everything and re-adding is not going to work any more.
What is the tried and trusted way of syncing Core Data with server side data?
Do I need to make a fetch request for each object id I get back from the server, and then update the object with the new data?
And then go through all of the objects in core data and see which ones have not been updated, and delete those?
Is that the best way to do it? It just seems a little expensive to do a fetch for each object in Core Data, that's all.
Pseudo code is fine for any answers :)
thanks in advance!
Well, consider your download. First, you should be doing this in a background thread (if not, there are lots of SO posts that talk about how to do that).
I would suggest that you implement what makes sense first, and then, after you can get valid performance data from running Instruments, consider performance optimization. Of course, use some common sense on "easy" performance stuff (your design can take care of the big ones easily enough).
Anyway, get your data from the online resource, and then, for each object fetched, use the "unique object id" to fetch the object from core data. You know there is only one object with that ID, so you can set fetchLimit to 1 on your fetch request. You can also configure your "object id" attribute to be an INDEX in the database. This way, you get the fastest search from the underlying database, and it knows to stop looking once it finds your one object. This should be pretty snappy.
Now you have your object. Change any attributes necessary. Save, rinse, and repeat.
Furthermore, for several reasons, you may want to know when objects were last updated. I'd suggest adding a timestamp to each object that gets changed with the current time every time an object is changed. This will also help in deleting objects. Since your online database does not tell you which objects are deleted, you must have some way to know that an item is "old and no longer needed."
An easy way to do this is to remember the time you started your update. After processing all objects from the download, you now have a way to find all the objects that were deleted from the online database. Basically, any object with a "last update" timestamp before the time you began the update should be removed (since they were not added or modified in the last update). You can also index the database on this field, which will make finding those objects faster - unless your database is huge, I'd wait to see what Instruments has to say about this one though.

Core Data delay when switching NSPersistentStore files

I'm developing an app with Core Data that periodically downloads all the data from a webservice. Since the download can fail or be cancelled by the user, I want to be able to roll back to the previous state. I tried undoing the NSManagedObjectContext, but that seemed a bit slow (I have tens of thousands of entities). What I'm doing right now is making a backup of the persistent store file, download the data, and, if the download fails, replace the store file with the backup. This seems to work correctly, except there seems to be a delay after I can fetch entities from the store: if after the download I go immediately to a UITableView that uses an NSFetchedResultsController, I find it empty. If I wait some seconds, everything is ok.
So my question is: has anyone had this kind of delays too? Is there something that can be done to avoid this problem, something that forces everything to be ready, even if it blocks the thread?
I haven't used this setup but I think the delay you are seeing is probably caused by Core Data having to clear all it's caching. Core Data uses If you use a cache with the fetched results controller it will have to test and then delete it's existing cache.
I think the best thing to do is to tear down you Core Data stack and reboot it from scratch. That includes recreating a fresh fetched results controller.

Resources