Title is the real question. But some advice + sample code re: how to cope within nsincrementalstore subclasses when there is no internet connection would be great.
I was thinking of caching to a sqlite persistent store so when an internet connection was unavailable I'd use a managed context that used the sqlite store instead of the incremental store.Not exactly sure on how the saving to the sqlite store would work to stay in sync with the web service (Parse in this case).
I suggest you rethink your architecture at a somewhat higher level.
Don't get down into the weeds of persistent stores and subclasses. Instead, think about the transactions you need to save.
Each modification you've made to the local store requires some sort of interaction with the web service. But those interactions are going to be messy: they'll fail, the server will be busy, network will come and go.
If you think about this in two parts, the local data update and the remote data update, you'll have much more hair remaining at the end of your project.
Related
This question is not about the technical problem, but rather the approach.
I know two more or less common approaches to store the data received from the server in your app:
1) Using managers, data holders etc to store the data. They are most often some kind of singleton and are used to store the models received from the server. (E.g. - the array of the posts/places/users) Singletons are needed to be able to access the data from any screen. I think the majority of apps uses this approach.
2) Using Core Data (or maybe Realm) as in-memory storage. This approach avoids having singletons, but, I guess, it is a bit more complex (and crash risky) to maintain and support.
How do you store data and why?
P.S. Any answers would help. But big "thank you" for detailed ones, with reasons.
The reason people opt to use Core Data/Relam/Shark or any other iOS ORM is mainly for the purpose of persisting data between runs of the app.
Currently there are two ways of doing this, for single values and very small (not that I encourage it) objects you can use the UserDefaults to persist between app launches. For a approach closer to a database, infact in the case of Core Data and SharkORM, they are built on top of SQLite, you need to use an ORM.
Using a manager to store an array of a data models will only persist said models for the lifetime of the app. For example when the user force quits the app, restarts their device or in some circumstances when iOS terminates your app, all that data will be lost permanently. This is because it is stored in RAM which is volatile memory, rather than in a database on the disk itself.
Using a database layer even if you don't specifically require persistence between launches can have its advantages though; for instance SharkORM allows you to execute raw SQL queries on your objects if you don't want to use the built in powerful query builder. This can be useful to quickly pull the model you are interested in rather than iterating through a local array.
In reply to your question, how do I store data?
Well, I use a combination of all three. Say for instance I called to an API for some data which I wanted to display there and then to the user, I would use a manager instance with an array to hold the data model.
But on the flipside if I wanted to store that data for later or if I needed to execute a complex query on it, I would store it on disk using Shark.
If however I just wanted to store whether or not the user had seen my on boarding flow I would just persist a boolean value into UserDefaults.
I hope this is detailed enough for you.
CoreData isn't strictly "in-memory". You can load objects into your data model and save them into their context, then they might actually be on disk and out of main memory, and they can easily be brought back via fetch requests.
Singletons, on the other hand, do typically stay in main memory all the time until the user terminates the app. If you have larger objects that you are storing in some data structure (e.g. full resolution images when all you really needed was a thumbnail), this can be quite a resource hog.
I want to write an app for both iOS and OS X which shares a common database and syncs via iCloud. I had planned to use Realm, but then wondered if it is a good fit when used in conjunction with CloudKit or should I use Core Data instead?
Thanks.
iCloud allows you to backup and sync files across all connected user devices. With Realm, you could theoretically settle on that as long as only one single client access the data to any point in time, which will be hard to guarantee. Furthermore there are restrictions on the file size, which will make this solution likely fragile.
CloudKit is a backend-as-a-service solution, which allows you to setup a schema and request your data from there. It doesn't bring a builtin persistence layer. You would need to provide that logic yourself, for integration with CoreData as for Realm.
I have an iOS app that timestamps some events and loads them in UI. To persist the data I use CloudKit which is quite fine and fast enough for my use case.
1st problem is, when an event occures I save it instantly to cloudkit therefore if internet is not reachable I have to handle the situation. I had the idea of having a local sqlite db and sort of keep track of connectivity and deal with syncing manually. Here is where 2nd problem comes in in which any inconsistency of the data must be handled by me (e.g. if the user edits the data while offline).
I found YapDatabase library doing the exact things but I feel the learning curve is a little bit steep.
Another idea could be using sqlite db but saving the file in the icloud drive. This way it will be persisted automatically while I have access to the app sqlite. Any change in the db tables will change the file singnature and fire icloud drive sync.
What's the best choice?
In my app I'm using RestKit v0.23.3 and I need to call 4 web service sequentially. I'm doing this without any problem following various tutorial that can be found on the web.
My problem is that I need to be sure to download all 4 services or data can be inconsistent.
Now my question: can I do a rollback on CoreData if one of the web services fails during the download/mapping operations ? Or is there a mode to disable the "auto save to persistent store" feature that RestKit has and save "manually" only when the last web service has ended ?
Thanks in advance for your help.
If this is really required then I'd be tempted to use a disk based solution - i.e. before you start any potentially destructive / corrupting operation you ensure everything is saved and make a copy of the data store on disk (note that multiple files may need to be saved so best to use API like
migratePersistentStore:toURL:options:withType:error:). Now, if you have a problem you can tear the Core Data stack down, restore from disk and then recreate the stack. This is safer and more reliable than trying to prevent saving or use an undo manager as the load process is run across multiple threads so you really need the saves to be running.
Design question:
My app talks to a server. Json data being sent/received.
Data on server is always changing, and I want users to see most current data, not stored/cached data. So I require a user to be logged in order to use the app, and care not to persist data in the app.
Should I still use CoreData and map it to Json's.?
Or can I just create custom model classes and map Json's to it's properties, and have nsarray properties, which point to its child objects, etc. ?
Which is better?
Thanks
If you dont want to persist data, I personally think core data would be overkill for this application
Core Data is really for local persistance. If the data was not changing so often and you didnt want them to have to get an updated data everytime the user visited the page, then you would load the JSON and store it locally using CoreData.
Use plain old objective-c objects for now. It's not hard to switch to Core Data in future, but once you've done so it gets a lot harder to change your schema.
That depends on what your needs are.
If you need the app to work offline, you need to store your information somehow in the client.
In order to save on network usage, you could store locally, then query the server to see if it had an updated answer -- you could do this by sending a time stamp to the server and return a 304 Not Modified if the entity hasn't changed.
Generally, it depends on how much time you have to put into the app and what your specific requirements are, but as a general rule I would optimise for as low bandwidth usage as possible, as that not only reduces potential data costs, but also means the answers will be more quickly available to your users (when online and they have not changed) and also available offline.
If you do not wish to store data locally at all,