I am creating an application that fetches data from a server (like an online address book) and uses it on the iPhone. Communication and fetching data work fine.
However, problems come into play when using Core Data to store the fetched info. (NOTE: I use SQLite as type of storage) Here is my set up and classes:
-- DSAccount. This is a subclass for NSObject. Holds fetched info from accounts fetched from the server (accountID, telephone, mail, etc). I use this class to display info inside a table view.
-- CachedAccount. This is a subclass of NSManagedObject, for Core Data. Holds exactly the same information as the DSAccount, only that I use that for storage.
Way of storing data:
-- Download the info from the server and make DSAccounts for displaying the information in the table view.
-- Then, for each DSAccount, I first check if an account with the same account ID already exists in the database (using predicates) and if there is not, I insert a Managed Object inside the core data database and populate its properties from the properties of the DSAccount. Then, I save.
However, I am experiencing performance issues on my device (even on my computer!) while saving. Consider that I fetching approx 9000 accounts from the online database, that I must save into my local core data database at once.
I feel that the way I have set up my data save store has problems. Can anyone maybe recommend me a better approach?
First of all you shouldn't have 2 objects for the same thing. Use only the NSManagedObject.
After you have refactored your code to only use one object per record you can go ahead and implement a NSFetchedResultsController for some super handy help with that UITableView of yours.
At this point you will have to stop and re-assess the perfornance issues and try to figure out where exactly they are. You will probably find that you need to download and process just chunks of the 9000 records. Maybe something like 200 at the time (your own testing will have to tell).
When this is all done in background threads the app should feel a lot faster and your tableview will be updated automatically by the fetched resultscontroller.
Then, for each DSAccount, I first check if an account with the same account ID already exists in the database (using predicates) and if there is not, I insert a Managed Object inside the core data database and populate its properties from the properties of the DSAccount. Then, I save.
Make sure that you have an index on the account ID property. Then use the -countForFetchRequest:error: method on the NSManagedObjectContext to see if the account ID exists.
If this still isn't fast enough, then you need to restructure the Core Data model so that account IDs are their own model object with a one-to-one relationship to the account info model object.
If that still isn't fast enough, then you need to forgo Core Data and use SQLite directly. Just make sure that you have an index on the account ID in all of these cases.