I'm new to Core Data, and I'm trying to make sure that I've got my data model and its usage set up properly.
I basically have two file types in my App ... one contains settings type data and a second contains data sets that the user will be working with (kind of like documents, although I can imagine the user working across 10s or even 100s of these files simultaneously).
I've been reading books on Core Data, and I remember reading that typically an app has a single NSPersistentStoreCoordinator, a single NSManagedObjectContext and a single NSManagedObjectModel.
I currently have a single managed object model with configurations for the various file types I have. I had been planning on also having one of the NSPersistentStoreCoordinators / NSManagedObjectContexts, and when I create new Core Data objects, I would make sure that each one was added to the correct persistent store.
However, I've seen examples where each file has its own NSPersistentStoreCoordinator and NSManagedObjectContext.
Are there advantages and disadvantages to having multiple NSPersistentStoreCoordinators and NSManagedObjectContexts in a single thread application?
Initially, I had been hoping to be able to move objects from one persistent store to another during user cut and paste type edits, but that doesn't seem possible either way.
Any advice is greatly appreciated!
Edit
Here is some more information about what is confusing me. When I read the documentation about NSPersistentStoreCoordinator, it says:
The coordinator is designed to present
a façade to the managed object
contexts such that a group of
persistent stores appears as an
aggregate store.
In my case, this is not what I want. I want my documents to be perceived as separate documents, and I don't want the queries to be confused between each other.
In addition, with only one persistent store coordinator and many persistent stores, if I forget to assign an entity to the correct store on creation, I find myself with bugs since entities are arbitrarily assigned to a valid store when they are created. I'm not sure what would happen with relationships that point to objects in different stores (probably an assertion failure?).
To me, it seems that having a single context / persistent store coordinator per store would be less prone to bugs, and allows me to keep the data for each document isolated from each other.
The only thing that a single persistent store seems to buy me is that I can perform a save operation for all stores simultaneously which would be preferable. With multiple contexts / store coordinators, I would need to perform separate save operations.
If you use the OSX NSPersistentDocument class, it seems to enforce a separate context / store coordinator per document.
Anyway, from all my research, it seems that separate store coordinators / contexts would work better for my App, but the reason I posted this is because I am new to Core Data and this approach does seem to go against the recommended flow and I'm worried that I'm missing some gotchas that will come back to bite me.
More Thoughts / Information
As I think about this more and read more feedback from others (thank you everyone!!!), my current thoughts are as follows.
For myself, there really doesn't seem to be that much difference between the two approaches and I currently believe that I could make it work well either way.
With a single store coordinator, I need to make sure that newly created entities are attached to the correct store (not really a big deal). With multiple store coordinators, I need to make sure that newly created entities are added to the correct context (of which I will have many of them). With the way my code is structured, either approach should be relatively easy for me.
I personally want to search a single store at a time. If I have multiple store coordinators, this is automatic. If I have a single store coordinator, I need to make sure to constrain the fetch request. (either way, not really a big deal).
The documentation for the store coordinator implies that its advantage is making multiple stores appear as one. For my app, I do not need or want that so this is not really a consideration for me (although if I wanted to add cross-store searching capabilities in the future, it would be best to keep everything in a single store coordinator).
To me, none of the above reasons are really good arguments either way, and if they were the only arguments, I would probably try to do things the more conventional way and stick with a single store coordinator.
However, one final reason (and the main reason that I originally posted this question) is that I am planning on taking advantage of some features in iOS 5 that seem to require multiple store coordinators. I want to be able to weak-link my app to be backwards compatible, so it seems that having my iOS 4 code closely resemble the iOS 5 code would be preferable.
The more I think about this, with the support for multiple OS versions, I could probably still implement things either way with the correct abstractions.
Thank you everyone for your feedback! I'm slowly getting the hang of Core Data which has mostly been a great experience, although its given me my share of headaches as well!
Generally an app will use only one PersistentStoreCoordinator and it is initialized in app delegate.
For more details and clarification please check the apples doc on Core Data
I can't honestly think of a reason why you would want to have a second coordinator unless you are performing some pretty serious concurrent, multi threaded tasks on the same model. From what you described above, you may only need to create a separate context for certain managed objects, or possibly separate stores if you need them to be completely independent.
You will hardly ever interact directly with a persistent store coordinator as most of your operations are done on the context level and then persisted when you are ready (again via context) through the store coordinator.
You've obviously done your own research so I am not going to tell you to check documentation XYZ (Core Data is well documented for basic level stuff but anything slightly more advanced and you are on your own), but my main point is that having a separate store coordinator for each of these models will probably increase the complexity of your code instead of making it easier to manage which seems to be your main motivation in the original question.
I don't see any real technical limitation to having multiple NSPersistentStoreCoordinator instances in your app as long as they are all pointed to a unique location on disk.
However, taking that approach is definitely not common and is going to add a lot of complexity to your app that may not be necessary. From what you've described about your data model, I don't see any reason why you'd need multiple NSPersistentStoreCoordinators.
Be sure to read the CoreData Programming Guide and know that you'll need to create a unique NSManagedObjectContext per thread, rather than per NSPersistentStoreCoordinator as you described in your question.
Related
Hi thank you for the help in advance,
I have looked at some of the posts and I am a bit confused about the multi threading. It seems that it may be pretty easy, however I am very new to programming so I am still trying to grasp this.
These are two calls to pull data from a database, and they take forever as it is... So I'm thinking about multithreading these until I can learn how to build a core data for this. Right now i am using sqllite and the database involves 10,000 + recipes... So not lightning fast like I would like...
Please let me know what you think, and how I can make these happen maybe simultaneously? (If thats even possible)
Thank you in advance.
requestCount++;
[[DataPuller sharedDataPuller] getAllDeletedRecipeList];
[DataPuller sharedDataPuller].target = self;
requestCount++;
[[DataPuller sharedDataPuller] getAllRecipesList];
[DataPuller sharedDataPuller].target = self;
If you're doing SQLite, you might want to contemplate using FMDB which (a) gets you out of the weeds of sqlite3 calls; and (b) offers a FMDatabaseQueue which allows you to coordinate queries from multiple queues, so that the data operations don't stumble across each other.
Having said that, you suggest that you're having significant performance issues which you're hoping to solve with a shift to Core Data or going multi-threaded with SQLite. That's unlikely. Poor performance of local database operations is generally more of a matter of your application design (e.g. it's unlikely to be wise to try to retrieve the entire details for all 10,000 recipes ... you probably want to retrieve just the unique identifiers, perhaps only those required for the given screen, and then only retrieve the particulars for a given recipe at a later point as you need that). For local database interaction, you rarely have to contemplate a multithreaded implementation, but rather just design the system to retrieve the least possible information at any given point that you need for the presentation. I personally find that my database-driven apps generally only need to go multithreaded when I'm doing extensive interaction with some remote web service (in which case, it's the retrieval of server data and the parsing of that which goes on the separate thread, not necessarily the database operations themselves).
If you're having performance issues with your recipe app, I'd suggest you submit a far more detailed question, with code samples, that articulates your particular performance problem. And I wouldn't be surprised if multi-threading was not part of the solution. Likely, appropriate use of indexes and a more judicious retrieval of information at any given point might be more critical.
Get records from database in the form of pages; i.e. 20 or 50 recipes per page. Have a look on YouTube app. on iPhone or have a look on my app. HCCHelper
I know little about Core Data. Read: I've read a few tutorials, kinda understood how it works, but never tried to use it in any of my apps. That said, I'd like to know if it's worth the effort to use it in the app I'm developing. Note that I'm not asking if I should learn Core Data, but if it's worthwhile to invest time learning it for this specific app I'm making, or if I should use archiving instead, ship the app, and only then learn Core Data in my spare time.
Basically my app reads a list of items from a web service, and needs to save the last N items. The user should also be able to bookmark items, so that's another thing I should store somewhere. So, right now I'm just archiving a subarray with range 0-N of the latest items. Does it work? Yes. Is it efficient, and the best way to achieve this? That's my question for you actually.
My doubt comes from the fact that whenever I see someone asking 'Is Core Data overkill for my project?' everyone suggests to use it anyway.
If the amount of data you need to persist can easily fit into memory without degrading the apps performance then you should just archive the array and ship the app.
Core Data gives a lot of advantages when handling large and complex data sets. It gives a lot of advantages in maintaining and upgrading a shipped app. However, those advantages should not get in the way of shipping an otherwise completed app. Later, you can always write code to migrate a shipped version to a Core Data version. It's more work, but hey, at least you've got a shipped app to work on.
I've seen a lot of small startups/developers come and go and the major factor that separates the successful from non-succesful is that the successful actually ship/release product. You can spend forever polishing an app but the key thing is knowing when to say, "It's good enough" and get the thing into the user's hands.
If it's a small list and you have the data in NSDictionary or NSArray collections, use writeToFile:atomically: instead for flat file XML Plist storage.
I still think you should learn Core Data eventually, but.
I have some doubts about SQLite...
My app uses only one table (encapsulated in a data logic class) to store small data, the connection is opened in didFinishLaunchingWithOptions and finalized in applicationWillTerminate (yes, I know that in iOS4 applicationWillTerminate is only called by iSO if necessary, but I write on database at every change of data).
Now I have to add a second table (and relative class) that will store different data (no join between the two tables) and of normal size (about 1-2 rows for day).
I thought of applying the singleton pattern to share the connection and the statements, but I read that for performance reason it's recommended to use class-local variables to hold the connection.
So what's the best practice? Singleton or two open connection?
What solution would you reccommend for my situation?
Thanks
Singleton for me when stored in the same database.
Small amounts of data shouldn't be a performance bottleneck anytime soon.
Or, of course, go with CoreData. :-)
For such a simple use, a singleton is probably the right answer for the very reasons that #Eiko mentions.
However, it all begs the question: Why aren't you using Core Data?
Using SQLite correctly is actually quite hard and I've seen dozens of very talented/experienced engineers get it entirely wrong without realizing it. Worse, scaling an existing implementation is even harder. Adding concurrency is really really hard with straight SQLite (and the Core Data engineers have expended a huge amount of energy and applied a ton of expertise to support concurrency on top of SQLite correctly).
For such a simple use, Core Data won't be hard to learn and it will leave you with a much more solid and versatile code base.
I have a rather simple iPhone app consisting of numerous views containing a single, grouped table view. These views are held together in navigation controllers which are grouped in a tab bar. Simple stuff.
My table views do little more than list text (like "Dog", "Cat" and "Weasel") and this data is being served from a collection of plists. It's perhaps worth mentioning too that these tables are 'static' in the sense that their data is pre-determined and will only ever be amended—and if so, very rarely indeed—by the developer (in this case, moi).
This rudimentary approach has reached its limits though, and I think I'm going to need something a bit more relational. I have worked a tad with Core Data in the past, but only with apps whose data is determined by user input.
I have four closely related questions:
Is Core Data overkill for an app consisting mainly of a selection of simple table views?
Do you recommend using Core Data to manage data which is predetermine and extremely unlikely to ever change?
Can one lock Core Data down so that its data can't change, thereby relinquishing my responsibility as the developer to handle the editing and saving of the managed object context?
How do I go about giving Core Data my predetermined data, and in a format I know that it can work with?
Thanks a bunch guys.
The answer is simple. If you do not need to persistent to an out of date format (like MSWord, etc.) then you should be using Core Data. Raw SQLite is a headache that is not worth the effort 99.999% of the time.
Core Data is more efficient than plists and allows greater flexibility if the project ever evolves.
It is also very easy to pre-populate a Core Data sqlite file using a OS X machine; you know, the machine you are using to develop your application in the first place :)
NNW's use case is a singular exception to this rule that, if I were a betting man, I would bet has the Core Data team's attention and will be corrected in a future update. An update, by the way, that you will get for free if you use Core Data.
You might consider using the SQLite API directly, rather than Core Data, as it may be easier to pre-populate a database that way. You can create and modify a SQLite database on any platform (Mac, Windows, Linux), and just copy it to your application's bundle as a resource.
You can find tutorials/examples that will create a user's database by copying a SQLite database out of the application bundle. In your case, you can just use the one in the bundle. Just be sure to open it read-only.
I would recommend sticking with plists since your data will rarely change and when it does it will be developer-driven.
Core Data is very powerful, but there will be a moderate amount of plumbing and infrastructure you'll need to set up to make it work.
Core Data places its store outside of your app bundle (as it must to run on the iPhone), so all new installations will need to load data into the store on the first run. This data will probably have to be stored as resource plists anyway, so you aren't saving yourself the trouble of generating those plists. Turns out that wasn't true and you can store read-only parts of the persistent store in the App bundle.
Since I don't know exactly what kinds of limitations you're running in too, Core Data may be the solution, but I'm guessing it won't be. If object relationships are the biggest difficulty you're dealing with, you should read up on object archiving as a way to store your entire object tree in a form that can easily be saved as a resource in your bundle and recreated when necessary.
You should read why NetNewsWire switched
The two main takeaways from that post:
I bet Core Data is the right way to go 95% of the time. Or more. It’s easy to work with. It’s fast (in most cases).
And:
(Rule: always work at the highest level possible.)
I recommend using plain SQLite. It is simpler, easier to maintain and you can build the database on non-mac systems, using many popular GUI editors. For me, using Core data is still a pain. Code to populate your tableviews from a static SQlite database is simple, straightforward, and transparent, while Core Data needs more boilerplate code which you don't even understand completely at first and overall has a lot of hidden complexity which you don't really need.
In the development of my first serious iPhone application (Meaning I'd like to actually get it out on the AppStore), I needed a good way to represent my data. Instead of going with core data, I (stupidly, I think) decided to use classes to represent my data.
I created three classes, MMDot, MMShowMovement, and MMShow. The MMShowMovement holds instances of the MMDot class in an array, as the MMShow holds instances of MMShowMovement. Sounded like a nice way to do it, each class has a lot of logic that has to go with it, so I thought that classes seemed like a good way to go about representing all this data.
My question is, is there an easy way to save the instances of these classes so I can restore the data after the application is reopened? I have made applications on OS X using a NSKeyedArchiver, would it be similar on the iPhone? Would it be easier to start again using Core Data instead (These objects are very complex, especially MMDot with about 15 instance variables, now that I look at it, maybe not THAT complex)?
I'm really at a loss here.
You can absolutely use NSKeyedArchiver to persist your objects. I'm a fan of either method, the decision mostly lies with your application needs. I don't think it will be much work to re-model your objects in CoreData. Without knowing anything about your application I'd say if you are doing simple persistence with a simple model you may not need Core Data, if you have complex relationships and will be reading/persisting data frequently during an application session Core Data is probably the way to go.
If you have a lot of object instances, you are probably better off using Core Data - it will help cache things, help you with queries to get specific sets of objects, and so on. KeyArchiving is really a lot more useful if you are saving off a handful of instances, but have some downsides - in particular it's harder to track down memory leaks from Unarchived objects.
Core Data can also do paging of results for you too, so that you aren't fetching in the entre contents of a large array if you do not need it.
I was looking into serializing my classes the other day and went with using NSUserDefaults. I just give all the internals of my objects a unique key based on the object. Seemed to work fast for me.
Wrote a blog about it here: http://technolojiadev.blogspot.com/2009/12/serialize-this.html