The question is rather simple. I know that there is SQLite. There is Core Data also. But I need something in between. More object-oriented than SQLite API and simplier than Core Data.
Main points are:
I need access to stored entities only by id. No queries required.
I need to store items of a single type, it means that I can use only one table if I choose SQLite.
I want automatic object-relational conversion. Or object-storage if the storage is not relational.
I can use object archiving, but I have to implement things (NSArchiver).
But I want to write some kind of class and get persistence automatically. As it can be done with Hibernate/ActiveRecord/Core Data/etc.
Thanks.
Everything you've said you want here is completely compatible with Core Data. Apple's giving you a solution that meets your stated needs exactly, so why are you trying to avoid it?
Beyond BNRPersistence, which Alex points out, I don't think you're going to find anything that maintains object relationships, yet is simpler than Core Data on the Cocoa platforms. An object wrapper around SQLite like FMDB still requires you to manage relationships in your own code.
Maintaining relationships between objects is a non-trivial task, which is why you see so few of these frameworks out there. Core Data gets it right for many people, so there isn't that much motivation among developers to build an alternative to Apple's solution. BNRPersistence was created out of Aaron Hillegass' long-time frustration with certain aspects of Core Data, but many people (like me) are perfectly happy with the way Core Data does what it does.
You might also want to look at Core Resource, a newer framework that provides some wrappers around Core Data to make common tasks easier.
You might consider a non-Objective-C approach to serializing objects, just as XML or JSON, where you don't have to write serialization code, if you don't want to, because the framework does it for you. For example, put your objects into a key-value attribute pairing with NSDictionary (via a wrapper class or whatever) that points to another record's id key, and then encode the mess with json-framework's JSONRepresentation call. You'd probably need to do your own relationship integrity tests, but voila, instant relational database.
Take a look at BNRPersistence.
Related
I am relatively new to iOS and programming, and I made an app before, but it used a plist for storage, which I saved to the documents folder. Now, I am thinking about switching over to Core Data, but it looks a little complicated, and I'm not sure if it will work for what I want. I am going to have a bunch of data which I need to graph, so I'm not sure if Core Data is best for this, as it seems that I cannot create an array type in the .xcdatamodeld file. What are some other advantages of Core Data? Is it faster? Easier to use (once you set it up)?
Update: For anyone wondering, I finished the app, and it was totally worth it to learn how to use Core Data, and it was a lot less complicated that I originally thought. Doing it with plists would have been hell. The way they go about doing it seemed a little cryptic at first but if you just start using it you will get it. The relationships are really what is awesome about it.
A few advantages off the top of my head:
Much better memory management. With a plist you must load the entire thing into memory; with Core Data only the objects you're currently using need to be loaded. Also, once objects are loaded, they're normally placeholder "fault" objects whose property data doesn't load until you need it.
Related to the above, when you have changes, you can save only the changed objects, not the entire data set.
You can read/write your model objects directly instead of converting them to/from something like an NSDictionary.
Built-in sorting of objects when you fetch them from the data store.
Rich system of predicates for searching your data set for objects of interest.
Relationships between entities are handled directly, as properties on the related objects. With a plist you would need to do something like store an object ID for a relationship, and then look up the related object.
Optional automatic validation of property values.
Data models don't use arrays, but "to-many" relationships are modeled as sets.
It's a matter of what you're saving. For simple strings, arrays, dictionaries, it's fine to use a plist. For something more complicated (data, images, non-object information) or something with to-many relationships (think relationship between song to album, or photo to photographer), then something like a more robust solution might work better like SQLite.
CoreData is an objective-c-based wrapper around SQLite. If you think you might want to something more complicated, CoreData might be the way to go.
If you need a quick tutorial, I'd check out: http://www.raywenderlich.com/934/core-data-tutorial-getting-started
This got me going and allowed me to learn the basics the workings of CoreData.
Good luck!
I've been looking into creating a new application for iOS and after my last few apps I've been tempted to use CoreData (for benefits including saving and automatic undo/redo).
I've been a little confused when trying to implement the data-model I've been given fr the project though, since it seems that CoreData seems very much much closer to a database than a data model.
Should I be using CoreData for an application that doesn't generally fit the 'large amount of data/records' description I would generally use an SQL style database for?
If it helps, the app I'm designing will be a sort of document editor, so there will be a number of objects I will need to represent (there might be embedded images, graphs/charts, hyperlinks etc within the document) and I need to create this model from an xml description.
Most of these 'items' need to implement a set of interfaces (the model was created for a Java product; I'm having difficulties seeing how inheritance and abstract interfaces can apply to CoreData), and every example I've found so far seems to add base elements (like an NSDate or String) to a simple model.
Does this sound like a candidate for CoreData, or is CoreData more of a tool for implementing a database in an application? (i.e a library system/staff database).
consider CoreData as an option once you are able to properly write the majority of the code it will replace. so once you know how to properly serialize/deserialize, write undo/redo, KVO, copying, etc.
Should I be using CoreData for an
application that doesn't generally fit
the 'large amount of data/records'
description I would generally use an
SQL style database for?
CoreData isn't restricted to large databases (at all) - it will work well with small sets, and beyond databases (binary files and documents, direct in memory use of models).
your example could benefit from CoreData. it depends on the amount of custom code you need - sometimes it is just easier to write the code if you're just using CD objects as an interface generator, and your app uses a lot of custom code/objects. to be honest, i've never used CoreData in a shipping app - i always found reasons to migrate models to existing code before then (assuming CoreData was also used during development/modeling stages).
it's a nice framework, but it shouldn't be viewed as a 'magic object generator' that will solve most problems. first, you need to understand he technologies/patterns you intend to replace with it. there is a limited number of ideal uses for it. if you can't write the code the objects depend on, don't bother using CoreData. iow - don't consider it as a replacement for initial effort because there are certainly times when it is a good choice and a bad choice - but you can't make an objective answer for your context if you don't (truly) understand what it is capable of.
One of the purposes of Core Data is managing an object graph in memory. This certainly fits your application. It can then be persisted to disk easily. Using a tool such as mogenerator allows you to use Core Data to manage the object life cycle, graph and persistence, but add your custom protocols on top.
In short, yes, you can use Core Data for non-database uses, with a bit of work to conform to the model.
I wonder in which cases it would be good to make an NSManagedObjectModel completely programmatically, with NSEntityDescription instances and all this stuff.
I'm that kind of person who prefers to code programmatically, rejecting Interface Builder. But when it comes to Core Data, I have a hard time figuring out why I should kill my time NOT using the nice Xcode Data Modeler tool.
And since data models are stuck to a given state (except when you want to do some ugly migration operations where thinks probably go wrong and users get mad, really mad), I see no big sense in a data model that's made programmatically for the purpose of changing it all the time.
Did I miss something?
I dont think you missed anything. The only reason I can see to create your model programatically would be if the objects you are modeling are themselves dynamic: you could for instance build a coredata entity (or graph of entities) in response to a web service which changed over time, or was selected by the user. However, I think if you had that or a similar use case, you wouldn't need to write this question (and you'd probably solve it a different way anyway)
So, if your application is dealing with resources that are dynamic, as #Andiih mentioned, then this programatic is the only way to do it. I don't know what my core data entities are until runtime, I don't know what the attributes are, or what the data looks like. So, I ask the server to give me the kinds of resources I should support and what their attributes look like. I build the model, the entities, the properties, the relationships - at runtime. I still want to use Core Data because I'm dealing with a lot of data and I need the benefit of efficient memory management with NSFetchedResultsController, etc. I can only do this programmatically.
The trouble is how to handle migration to try and preserve as much of the persistent store as possible, to reduce the size of the networked data payload after the model changes. Right now I blast the whole model and the persistent store if there's a conflict. I haven't yet figured out a way to create an .xcdatamodel from a programmatically generated model, thus I can't yet create a version mapping to do the migration.
Everything is a trade off. Basically, I think IB and the visual Core Data modeler are the right tool if you're building a simple application. You'll need to make the determination when your application becomes large/complex enough that you prefer to have direct control over all aspects of the code.
Regarding Interface Builder, if you have an application with a variety of complex interactions between view controllers, and multiple custom controls, I find code more appropriate.
For Core Data, the question is pretty much the same. Does your project have a defined scope? Can you foresee everything in that scope being done within the visual modeler? If so, it's probably fine. For other projects, where you may be asked to add features on an ongoing basis, perhaps it's better to spend a little more time writing it out so you have more flexibility later.
One other thing to consider, that doesn't get mentioned much, is it's MUCH harder to ask for help with IB or any hybrid visual design/code system. When something does go wrong, or you need help, it's way easier to post your code, than try to explain what's going on in a visual modeler.
In general, there's no reason to build the managed object model in code. There's nothing you can do in code that can't be done in the model editor. There are some fancy tricks you can do in code, however, to work with multiple models. For example, you can merge two models, establishing cross-model relationships between entities in those models at load time (see Cross-model relationships in NSManagedObjectModel from merged models?).
Regarding whether it's a good idea to code or use the graphical editor, I think the balance tips heavily towards the graphical editor in this case. Being able to verify the model by visual inspection instead of (rather convoluted) code is a win. The model can still be verified by unit test, if you desire.
I have one use case that might be valid, what if you load some data from the internet whether it is XML from an RSS Feed or WSDL response, then flatten those responses into a tabular from generating an in memory data table and finally mash it all up into a single coherent data model, then you can create the entities for those in memory data tables and create master/detail relationships. That's one case I think Core Data data model generated programmatically could become handy and a powerful feature.
I've changed models programmatically in unit tests. For example, I wrote a class that is designed to work with Core Data models that have a particular protocol attached. Instead of testing against a random implementation, I mutated the default model by adding one just in the unit tests programmatically, and tested against that test-only model.
I have an app developed for iPhone OS 2.x. For the obvious reasons, the model classes in that app were written without Core Data.
Now that 3.x is available, I'd like to know what are some of my options for taking my existing model classes and rebuilding them with Core Data. I do many things with my models besides the obvious, such as serializing them and storing them into an sqlite3 database so that my application can work when there isn't any network connectivity. I would expect Core Data to be able to help me with that as well.
Also, with the incorporation of Core Data in your application, is there any reason at all to still use sqlite3? Would you still use it for things such as providing for offline content, keeping around statistics that might not necessarily make sense to create a model out of? Or is there ways of incorporating all of that into Core Data as well?
The primary benefits I've found from using Core Data in my iPhone applications are:
Keeping referential integrity
Managed model migration on schema changes
providing an object relational mapping
Vastly simplified insertion and join and query process - joins for instance are typically just done through "dotted" syntax
Multiple store overlaying (although look for my stackoverflow question about this to see if it actually works on sqllite, still awaiting response...)
Structured predicate construction - you can create your predicates as objects instead of inline embedded sql statements
Reflective data store - you can introspect the data store at run time in a structured and statically analyzable way
That said, if your app already has been designed to work against a sqllite database, you really need to ask yourself if you're ready to convert your application over.
You will need to do at least these things:
Remodel your entire database schema in Core Data managed object models
Rewrite all of your database queries and management to use Core Data
Rewrite all of your models to either be backed by Core Data generated managed objects, or extending them
Import all of your existing data by hand into your Core Data database
Be prepared for potentially writing a lot more code! Although Core Data provides a good object framework for dealing with data store querying and management, it also does so at the expense of verbosity.
To continue the previous point, when you do even relatively minor changes to your schema, you're going to be prepared to spend a relatively significant amount of time providing a schema mapping and applying it correctly to your existing schemas.
Give you already have solved almost all of these issues already, the benefit you would get form porting an existing application to Core Data is elegance and keeping up with latest technology. You will have to provide a not insignificant amount of effort to get that, and given the benefits probably aren't stupendous, you might find it not really worth your while.
To answer your second question, I can't really think of any reason for using sqllite directly if you are using Core Data to be honest. I'm not certain that outer joins are terribly simple in Core Data for instance. However, you don't typically use Core Data in that manner - you would use it procedurally to craft the same effect as the outer join in SQL.
For statistics and stuff I would still use Core Data because it provides some fantastic aggregation functionality.
Note there is nothing preventing you from taking the opposite approach: adopt Core Data for extended functionality until you become comfortable enough with it, then begin porting your main applications existing code to use Core Data.
The other answer is very good, but I disagree on the benefits being mainly elegance and keeping up with technology... the real reason to move to Core Data is actually performance and memory related, in the Core Data manages caching very intelligently and you'd have to do a lot of work to replicate that. That to me is the sole reason to even consider it, as it is very verbose as noted and you also have to work around all data objects needing to use NSNumber to hold primitive values (which I find particularly annoying).
For something like your setup, the approach I'd probably take for migration is to have each model class hold on to managed objects that are actually the storage classes - then your whole code would not have to change, just some things in the model objects and possibly management classes you might have built to handle creation or population of the model objects. That even hides the NSNumber wrapped primitive issue.
If you are strongly considering working with Core Data, you may want to take a look at this book that covers the iPhone specific Core Data as well (including NSFetchedResultsController):
http://www.pragprog.com/titles/mzcd/core-data
You can buy an e-book only unlocked PDF version which is not too expensive...
We're beginning development of an in-house app in the iPhone Enterprise developer program. Since it's close to OS 3.0, we're reconsidering our original design of using SQLite and using Core Data instead. Here's some more info:
There is a legacy desktop application that this is replacing. We will reuse the existing back end.
We currently have a SQLite database generated as a proof of concept. This is basically a cut down version of the existing back end database.
We will be loading data from a remote site and storing it locally, where it will persist and need to be . We only update it if it has changed, which will be every month or two. We will most likely use XML or JSON to transfer the data.
There are two developers on this project and we both have strong SQL skills but neither one has used Core Data.
My questions are: what is the benefit of Core Data over SQLite, what would the benefit be in this specific instance and do the benefits justify learning a new framework instead of using existing strong SQL skills?
EDIT:
I just noticed this question: Core Data vs SQLite 3. I guess my questions therefore are:
If I have to check if a specific item either exists or has an update, which is easy using SQL, does Core Data still make sense? Can I load the first object in a graph and check the version number without loading the whole graph?
If we already know SQL, does the advantages of Core Data for this one project justify us learning it?
As you've read Core Data vs SQLite 3, you know that Core Data and the persistence mechanism (SQLite in this case) are largely orthogonal. Core Data is really about managing an object graph and it's main use case is for the model component of an MVC architecture. If your application fits nicely into this architecture, it's probably worth using Core Data as it will save you a lot of code in the model component. If you already have a working model component (e.g. from the existing desktop app), then Core Data won't buy you much. A hybrid approach is possible-- you can do your own persistence/querying and build a Core Data in memory store which you populate with the result of a query and use this in-memory store via Core Data as the model component for your app. This isn't common, but I've done it and there are no major roadblocks.
To answer your specific questions:
You can assign a version number to the entire persistent store and retrieve that information via +[NSPersistentStore metadataForPersistentStoreWithURL:error:], without even opening the store. An equivalent +setMetadata:forPersistentStoreWithURL:error also exists, of course. If you want to store the version info in an entity instance instead of in the persistent store metadata, you can load only a single object. With an SQLite persistent store, Core Data does a very good job of fetching only what you need.
The NSPredicate API, is very easy to learn and it seems to do a decent job of compilation to SQL. At least for databases of the size you could fit on an iPhone it's certainly been adequate (performance wise) in my experience. I think the SQL vs. Core Data question is slightly misguided, however. Once you get the result of a query what are you going to do with it? If you roll your own, you'll have to instantiate objects, handle faulting/uniqueing (if you don't want to load the entire result of a query into memory immediately) and all of the other object graph management facilities already provided by Core Data.
It sounds like you already have the project designed using SQLite, and you have experience in that area.
So the bottom line is, does it make sense to port this project, will Core Data give me anything that I didn't already have in my original design?
Assuming that the original design was done properly, based on the requirements ON THIS PROJECT, it's probably not worth it.
But that's not the end of the discussion. There are other things to think about: Will my next project have such light database requirements? Do I need to ship soon, due to timeline or budget constraints? Assuming I'm going to have to learn Core Data sooner or later, doesn't it make sense to do it now? Am I possibly interested in porting my code over to the Mac?
The answers to these questions may lead you to the decision that yes, it is indeed worth it to go back to the drawing board so to speak, and learn what Core Data is all about.
To get to your final question: What are the advantages? Well, Core Data is a higher level abstraction of your database, it is also data store agnostic (so if a future version of the iPhone were to ditch SQLite for an embedded version of MySQL... unlikely, but it's an example) then Core Data would require VERY few changes to the code to make it work with the new data store. Core Data will provide a great deal of quick portability to the Mac platform. Core Data will handle versioning of your data model, whereas unless you have a framework or a workflow to manage it, direct access to SQLite won't.
I'm sure other answerers can come up with other advantages, and maybe some good reasons why NOT to mess with Core Data. Incidentally, in a similar situation, my decision was to port to the higher level, newer framework. But in my case, it was for a side project, and ship date and budget were non-factors.
Not to detract from this forum, but you might find more respondents with contextually relevant experience at the Apple iPhone DevForum.
Speaking from a purely project management perspective, it sounds like you know how to build what you want to build using SQLite, and so it would make more sense to me for you to start along that route.
That being said, CoreData builds on top of SQLite and if you are trying to leverage other parts of the system in conjunction with your data, e.g. using KVC/KVO or bindings, then you may quickly find that this functionality is worth the learning curve.
= Mike