Core Data Classes vs Model - objective-c

I've recently started down the road of programming in Objective-C, and I'm now looking into Core Data. However, I am confused about exactly what defines the model itself in Core Data.
Here's what I mean: Say I create an entity with some set of attributes using the graphical model builder. I then have Xcode generate code for the corresponding class. Next, I want to create a property in the class that will be used only during run-time and does not need to be stored or retrieved by Core Data. So, I add a variable and a corresponding property to the class (synthesizing it in the implementation)
The new property is not defined in the model builder, but it is defined in the class derived from NSManagedObject. How is it treated in Core Data? Do the properties listed in the class define attributes in the "model" or do only the attributes defined in the model builder define the model?
Similarly, I wanted to add a enum-based property to the class file that, when get or set, accesses or changes an NSNumber attribute in the model. Can I do that without Core Data treating the property as an attribute to be stored and retrieved?
THANKS!

You can add custom properties (and variables) to the code generated for your NSManagedObjects, as you would any other class. These won't become part of the model, but instead will be temporary in memory. It's worth noting that if the managed object were to be dealloc'ed the value in memory would too.
A tip I would suggest if you are just implementing custom accessors to the underlying data is to create a category on the managed object in question. In the accessors, you access the underlying NSNumber and convert it into your enum, defined in the header for the category.
If you need to regenerate the code for the managed object, because say the model changes, you can just delete the class generated for the managed object and regenerate it without needing to merge with any custom code you've added. The category you've added will work all the same as long as the underlying storage property has stayed the same.
You can find out more about categories in the Objective-C Programming Language guide at the ADC.

Related

Correct way of dealing with Core Data NSManagedObjects in an iOS application

When I have worked with Java applications involving a database and ORM (object relationship manager) the architecture was usually separated so when working with database entities in the database layer you worked directly with the entities. But if you needed to access the entities in the GUI you would create a data transfer object (DTO) of the entity and then use it in the GUI layer.
What is the preferred approach in iOS applications?
One example would be that I do a fetch from Core Data to retrieve some objects in a ViewController and then display the results in a TableView in the ViewController. Is it necessary to convert the NSManagedObjects to DTOs before showing the results?
What is the preferred approach in iOS applications?
Is it necessary to convert the NSManagedObjects to DTOs before showing the results?
No, it is not neccessary. The managed object is already a (generic) object wrapping the database entity. You can access the managed object's properties (ie the entitys attributes) using -valueForKey: calls.
But the preferred approach is to subclass NSManagedObject to fit your entities. In Xcode there is an option to generate subclasses automatically (editor-> generate NSManagedObject subclass). That way you get your own subclass object for your entities and can access their properties using dot notation.
On fetching objects, just let the result be of type of that subclass.
If you want to add custom methods to your entity objects, you should create a category on your managed object subclass. This is because if you change your db scheme and have to let xcode recreate your subclasses, it completely overwrites the and your custom methods would be lost.

Core Data, iVars and Categories

One of my core data subclasses has an NSSet of items. It is often (but not always, so no NSOrderedSet) useful to instead retrieve an ordered NSArray, so I added orderedItems to the class, which sorts them.
I then ran into performance issues so decided to try caching the orderedItems. My plan is to use an iVar, _cachedOrderedItems in the class, which I will return if it is not null.
The snag comes with my use of categories. I read some good advice about putting all of my custom code in a category so that I can re-generate the core data class if necessary and not lose all my customizations. One of those customizations is the orderedItems method.
It seems I can not declare an iVar in the category itself. And if I try to put it in the core data class instead, I can not access it in the category.
Do I need to move my custom code back into the core data class? Or am I missing something?
I have also heard about Mogenerator, and would consider learning to use this if it would help.
You can use associative references to add ivars to a class any time you can't modify the original class, including in categories. For a detailed example, see Faking instance variables in Objective-C categories with Associative References.
You own the class, so you can use a class continuation (discussed here) instead of a category. This allows you to add instance variables.
You should definitely use mogenerator. See for example http://importantshock.wordpress.com/2006/12/19/mogenerator-or-how-i-nearly-abandoned-core-data/.
You can make an Aggregate target in XCode, add a Run Script with the following:
mogenerator -m path/to/your/datamodel.xcdatamodeld/version.xcdatamodel --template-var arc=true -M /CoreData/Generated -H /CoreData
For every NSManagedObject you get a class and a subclass. When updating your datamodel, run the script again and the base class will be updated, preserving all the changes you made to the managed object subclass. Remove --template-var arc=true for none arc.

How much does Core Data store?

Just a small question I can't find an answer to.
If I add a data model, including all attributes for each class, and generate core data classes for these, I can of course get everything to persist.
But I can also add non-core data attributes to a class. Will these persist also? Simply by virtue of belonging to a stored object? Will it be any different for basic data types vs objects?
I would assume these will not be saved, but thought it was worth checking.
No. Core Data only saves modeled properties. It's perfectly fine, and often desired, to add additional properties to your NSManagedObject subclass, but they'll behave just like properties on any other object and will not be saved to disk.

impact of core data on existing project iphone

I am starting to have a look at Core Data, as many claiming is the best way to persist data.
I have an already working project with its model and objects, the main purpose of the application is to encapsulate things as attributes (NString,NSObject, Custom Object..ecc) into one main class, give the ability to create many instance of this class then save it to storage, later retrieve and display a table list with all saved instance.
In this case, where my class is already defined (as NSObject extension), what could happen with the introduction of Core Data ? Do I need to rewrite my model ?
For example as a first try I created a model in xcode, then associate my object as entity to it. But some of the attributes that were not using standard such as string, int ...ecc got UNDEFINED as type.
#interface Car {
NSString *name;
WheelsType wtype; <-- undefined
NSDate *buy;
CarColor *color; <-- undefined
}
#end
What does that mean ? Am I able to save just only String,Int,Boolean...ecc but not my Custom Classes ? If not, what the table structure could be ?
thanks
Custom types in CoreData can be declared transformable, meaning that they'll be transformed to and from instances of NSData. The default value transformer works in many cases, but your classes may require a custom NSValueTransformer.
Edit:
Since utilizing CoreData changes how you retrieve your data, it'd be wise to review your model. Read the CoreData documentation and then consider how your objects are accessed and how you can avoid faulting objects and properties that will go unused.

Instance variables of custom classes in NSManagedObject subclass

I have written a class Foo, and would like to include a Foo object as a property for an NSManagedObject subclass. Is this possible? Can Core Data store information other than strings, booleans, integers, etc.?
One way is to write an NSValueTransformer that transforms your Foo object to NSData. Make the attribute "Transformable" and give the name of the transformer in the attribute settings.
For more details or information or other options, see the Core Data Programming Guide, in particular the section "Non-Standard Persistent Attributes".