Does Core Data undo management work across application restarts? - objective-c

I have been getting my feet wet with Core Data. I'm writing a card game and I'm able to store and retrieve game statistics. I'm also storing the game's state after each move to allow the application to resume a game that was in progress when the application quit and to also facilitate my home-brew undo system.
Unfortunately, the longer I play my game the slower it feels. I think this is because after each move I'm storing 52 cards and their specific states in SqlLite. I suspect that this just gets slower the more data I cram into the DB.
Because of this, I plan to try using the built-in undo management in Core Data. (I didn't remember this was there until it was too late on my initial implementation.) My question is, if the app is closed mid game, can it be restarted with the undo management in the same state?
IE: Imagine a user makes ten moves in this game. They would be able to undo ten times. If they quit the app and close it entirely and then restart the app, can I return Core Data to a state where the user will still be able to do the ten undo steps?
A little bit of research suggests I might be able to simply use NSCoding to persist the NSManagedObjectContext to a serialized file when the app is closed and then restore it's state from this file when the app is restarted.
Am I on the right path? Any suggestions?
Thanks!

NO UndoManager is not persistent.
Yes you may use NSCoding or even a Plist for saving the state.
For more information on this topic you may refer
http://www.cimgf.com/2011/10/11/core-data-and-the-undo-manager/

Related

CoreData main application and background process, with the same data

I'am planning to have a main OSX application, which the user can launch and a background process, which starts on OSX startup and runs prior to the main application
I need a CoreData database, to keep track of some changes... this database should be the same for the background task and foreground app...
What are the options?
Is it possible, that both access the same sqlite (which will be
located in app bundle?)? By setup with the same .sqlite file?
Should they have two identical databases, which they synchronize?
can this synchronisation be automated?
Should there be one database for the background process and the
main application should communicate with the background process?
Using a background process to update the datastore is fighting the frameworks. Also, your background process (and your main process, for that matter) won't be able to update the .sqlite file that lives in your bundle.
Instead of using a background process, use a background queue (via Grand Central Dispatch, and NSManagedObjectContext -performBlock:. Keeping the logic within one application will make your life easier. Your communication happens within the application, instead of having to use XPC.
Don't forget to handle the case of a partial, interrupted, update. The sequence I suggest is:
Application launches.
Background queue launches, pulls updated info from server, creates updated datastore using a temporary name.
If background update succeeds, main queue of application closes the old version of the datastore, then replaces it with the updated datastore. There is API to do this atomically.
Main thread reopens datastore and refreshes UI as needed.
If background update fails, reschedule an update attempt based on failure reasons (bad credentials, server unreachable, partial download, corrupt .sqlite).
If you're absolutely dead set on using two different processes, then you should still assume that the update might fail. So don't write to the live copy until you know you have a complete, valid, replacement.
Apple achieve this in the Notes app using what they call a "cross process change coordinator". This allows the accountsd daemon and the Notes app to access the same CoreData sqlite database. Their class ICNotesCrossProcessChangeCoordinator in the NotesShared framework works by using NSDistributedNotificationCenter to post the notification of changes between the processes and merge them into each others' context. There are many more implementation details of the technique but this should point you in the right direction.

Performance of Application object vs. MSSQL DB

I'm currently working on a chat application using vb.net and my current design uses an Application object that when users send messages, they are appended to the application object and when retrieving messages, they are just reading from where they left off in the object. The only alternative I could think of would be to have an MSSQL table where messages would be inserted to and read from using a key to know where the users last read left off. What are the pros and cons to each of these implementations, and is there a method that I'm overlooking that would be more ideal?
As far as I can see, the advantages to the application object would be speed because you don't need to open a connection every time you make a read or write, and locking isn't necessary when reading the object. The disadvantages would be an application object getting very large and taking up too much memory, and if the application pool goes down, the chat would be lost with the object.
Advantages to an MSSQL table would be the datas persistence and structured storage and retrieval. Disadvantages would be having to open a connection every time which I assume would cause performance issues and collisions when multiple people try sending a message at once.
The chat so far has had a high of 400 users and I'm expecting it to reach into the thousands so performance will definitely be a concern in the near future.
Well, there is also one big disadvantage to using the Application object. It won't work if deploying to a webfarm, since the object is not shared across servers.
If those were your only two options then I'd definitely go with a database, for scalability reasons.
However, another approach you might want to look into, especially if this chat app is embedded in a web application, is using SignalR, which is basically built for this kind of scenario.
Here's a tutorial on how to create a simple chat application using SignalR:
http://www.asp.net/signalr/overview/signalr-20/getting-started-with-signalr-20/tutorial-getting-started-with-signalr-20

When best to perform iCloud Sync

I'm syncing a list of table view items via iCloud. When would be best to perform the sync. Here is my understanding of the various options.
didFinishLaunchingWithOptions - this will only get called when the app is launched. As most users send the app to background, rather than quit, it is likely this method won't be called very often.
applicationWillEnterForeground - this will happend every time the app is opened from a background state, if the internet connection is slow, this could cause a pause is the UI displaying?
applicationDidEnterBackground - I believe we only have 5 seconds to perform any actions, so a slow connection might mean we can't sync.
What are your thoughts best time to sync?
Well, besides the fact that a document saves every so odd amount of seconds, the best time to sync with iCloud is very dependent on the circumstance.
For example, if you have created a brand-new object that would be lost if not stored to iCloud, it's probably a good idea to do a sync with iCloud right away.
On the contrary, if you have created a brand-new object that wouldn't be lost if not stored to iCloud due to it being saved within Core Data, then maybe you can combine the save into one elsewhere given that you're concerned about the speed and CPU that the sync will take up.

When to store local data in my Windows 8 Metro Application

I am a developing a Windows 8 metro application that has a set of settings that the user can specify. I know of a few ways to store these settings in the local storage so they can be restored when the user resumes/re-starts the application.
What I want to know is when should I store this data? Periodically? On Application Close/Crash? When exactly? What are the conventions?
I'm not aware of any convention / best practice.
The most convenient way is to have all application data in one big class instance, deserialize it at startup and serialize it on close/suspend. This way you need only few lines of code and nearly no logic. A positive side effect is that during operation the app isn't slowed down by loading/saving.
However when the class gets too big, you might experience a noticable increase of startup/shutdown times of your app. This could ultimately lead to being rejected from marektplace. In this case I recommend to save each small bit of information (e.g. a single user setting) instantly, and to load each small bit of information not before it's required.
I would have thought that to some extent that depends on the data. However, you will need to store the current state of the app on the Suspending event (which may also be the close event).

How to migrate a Core Data persistent store without process being killed on iOS?

I use Core Data to maintain a persistent store, and the database can grow quite large. My users with larger databases on iPad 1s don't complete the lightweight migration in time for the process to complete before the app is killed by the iOS for hanging.
What I want to do is every time the server starts up, check to see if the database needs to be migrated (I can't find a method for this on NSPersistentStoreCoordinator), if it does hold the server startup process until the database is upgraded and display a spinner on screen, then move forward with the server startup process once it is. The best way to do this seems to be to add a - (BOOL) upgradeStoreNeedsUpgrade method in the server startup method, but I can't find a way to check. I don't see methods on NSPersistentStoreCoordinator or NSPersistentStore to check the compatibility of a a database at a given URL with a given managed object model.
Is my solution the right way, and if so, how can I check if the managed object model is compatible with the SQLite file at a given URL?
You could try wrapping the core data lightweight migration code in a dispatch block. This should spin it off to a background thread so you can get past the Application Start Watchdog thats probably killing your app. Its either that or you are running the device out of memory.