Why would I want to have a non-standard attribute? - iphone

The documentation on Core Data entities says:
You might implement a custom class,
for example, to provide custom
accessor or validation methods, to use
non-standard attributes, to specify
dependent keys, to calculate derived
values, or to implement any other
custom logic.
I stumbled over the non-standard attributes claim. It's just a guess: If my attribute is anything other than NSString, NSNumber or NSDate I will want to have a non-standard Attribute with special setter and getter methods? So, for example, if I wanted to store an image, this would be a non-standard Attribute with type NSData and a special method, say -(void)setImageWithFileURL:(NSURL*)url which then pulls the image data from the file, puts in in an NSData and assigns it to core data?
Or did I get that wrong?

A non-standard attribute can be anything. Some common examples are:
an image
a binary key
encrypted data
audio
Just about anything that cannot be represented as a number or string falls into this category.
update
Transformable is not a data type of it's own. It is a way to say that a non-standard value is going to be stored here. Under the covers it is binary. The Transformable tag is a hint to Core Data to go look at the subclass's property setting.

Related

what is the use with the transfarmable in the xcdatamodal extension

hi all just now i started database work for my app.my idea is to save some rectangles(x,y,width,hight individually)as int32 and nsstring as string upto that my work completed .Now my question here is, what is the use with the "transfarmable" type where we can use this. Thanks in advance for your answer.
I'm not sure about transfarmable, but Transformable is:
The idea behind transformable
attributes is that you access an
attribute as a non-standard type, but
behind the scenes Core Data uses an
instance of NSValueTransformer to
convert the attribute to and from an
instance of NSData. Core Data then
stores the data instance to the
persistent store.
By default, Core Data uses the
NSKeyedUnarchiveFromDataTransformerName
transformer, however you can specify
your own transformer if you want. If
you specify a custom transformer, it
must transform an instance of the
non-standard data type into an
instance of NSData and support reverse
transformation. You should not specify
a name if you are using the default
transformer.
as taken from http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdNSAttributes.html.
Essentially, if you want a custom construct to be serialized into the database and then reconstituted as your desired object/object graph, the Transformable type lets you access Core Data's framework for storing complex formats/objects in the database, letting you code the logic that does the serialization and deserialization.

why would I need to use a primitive accessor methods in a core data project?

Why would I need to use a primitive accessor methods in a core data project?
I'm reading about Core Data and note the below:
By default, Core Data dynamically
creates efficient public and primitive
get and set accessor methods for
modeled properties (attributes and
relationships) of managed object
classes...
For example, given an entity with an
attribute firstName, Core Data
automatically generates firstName,
setFirstName:, primitiveFirstName, and
setPrimitiveFirstName:.
I'm still not sure what the primitive accessor methods are? How do they work? When & why would I need to use them over the normal accessor methods?
thanks
In normal classes, you would not usually use primitive accessors, but Core Data uses them frequently. The most common scenario: You write a custom accessor (to perform maintenance, create a default object, handle transient wrapper of persistent property, etc.) but want to use Core Data's optimized storage. If the optimized accessors were normal accessors, your custom one would prevent it from being available, but instead you just have to use the primitive accessor.
Also, the default accessors you get from Xcode include methods to add or remove objects from to-many relationships. If these methods used normal accessors, the normal accessors would trigger change notifications for the entire set. Instead they use the primitive accessors and create their own change notifications for just the part they are changing.
The most important thing is that the primitive accessors are the only way to get to the optimized storage. Without them, you would have to use instance variables, which Apple advises against.
If you are writing your own methods in a subclass of NSManagedObject, the primitive accessors enable you to get directly at the data the object contains.
Effectively, you would use them the same way you would use an instance variable in a normal class.
The primary use of primitive accessors is to prevent key-value observing notifications from being sent when you change a value. Sometimes you do not want such notifications sent because they have quite a bit of overhead. E.g. when importing large sets of data or when you use a transitory value to alter a persisted value.
You use them almost always when writing customer accessor methods. If you look at the accessor methods generated by Xcode for managed object subclasses, you can see how they are used.

What exactly are those data types int 16, int 32 and int 64 on the iPhone, in Core Data?

The Xcode data modeler shows me those three different int data types. When I would write code, which data types do these really correspond to on the iPhone? Are they all simply NSInteger, wrapped in an NSNumber?
As far as I see it, NSNumber only differentiates between int an NSInteger... so I guess those three end up beeing pretty much the same?
Those values correspond to the NSAttributeType of NSAttributeDescription. These are analogous to the strings returned by NSValue's objCType method inherited by NSNumber. The core data framework needs to know how to encode/decode the value in the persistent store and also which init method to call when creating the NSNumber object. The types in NSEntityDescription provide the ability to dynamically create the correct object from storage and save them again. Generally, you don't need to be concerned with the storage details of the NSValue classes and subclasses. These details are hidden on purpose. If you were implementing your own custom NSAtomicStore then you will need to know. Consult the Atomic Store Programming Topics for further details.

iPhone Core Data: Do Transformable Attributes have to Transform to only Data?

I've been using transformable attributes in core data to transform complex objects like images and colors into raw data. I took this...
The idea behind transformable
attributes is that you access an
attribute as a non-standard type, but
behind the scenes Core Data uses an
instance of NSValueTransformer to
convert the attribute to and from an
instance of NSData. Core Data then
stores the data instance to the
persistent store.
... to mean that you could only convert things to and from data and not one of the other types of attributes such as strings.
It just occurred to me that this might not be the case. The documentation might just be talking about the most common case. IIRC, in Cocoa bindings, the transforms can be largely arbitrary. It is possible to transform, say, a NSURL to a NSString for display and then reverse it.
Before I waste time experimenting and possibly getting a confusing result, I wondered if someone knew for certain if the transform is only to and from data only.
Correct. You must transform your attribute into an NSData object. You would need to serialize an NSURL to NSData -- and the default NSKeyedUnarchiveFromDataTransformerName transformer will do this for you.
Another approach, and the one that I use for URLs, is to maintain two parallel properties. One transient property of undefined type for the URL, and a second persistent property of string type for the backing store. I lazily construct the URL from the string the first time it's requested, and I update the string property whenever the URL is changed.
There's no way to enforce it, but you really don't want to use the string property from outside your entity's class. I generally make the #property definition for the string attribute private to remind myself not to use it.
I don't have enough points to comment, so I have to contribute in the form of an answer. I just tried to do exactly what #Amaud suggested, using an NSValueTransformer to convert NSURL objects to NSString objects for a Transformable attribute. Unfortunately, Core Data still expects an NSData instance from the transformer, regardless of the transformedValueClass. Core Data still creates the SQLite database with a BLOB column for that transformable attribute, and saving entities results in a crash with uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString bytes]: unrecognized selector sent to instance 0x608000075bc0'. Core Data is trying to invoke [NSData bytes] on the NSString instance my transformer provided. This seems like a big hole in Core Data to me, as I'm sure there are countless non-standard types that could be stored and queried as string attributes.
It seems the only option, aside from using NSString, is to do as #Alex describes and use transient properties and derived values. Core Data does not make that very clean, however, because as #Alex stated, there's no way to enforce exclusive use of the transient property accessors.

Key-Value Coding

I had a straight forward approach of turning Key/Value pairs of an XML excerpt into an NSDictionary when I started a simple iPhone application. The problem is, I need to turn those NSDictionary's instances that once populated my UITableView's into custom classes because they require behavior and additional complexity. The problem here is that now in order for me to instantiate an object and fill its instance variables with key/value pairs from a web service becomes that much more difficult. I can no longer throw it into a method that iterates through the XML and uses KVC to set its instance variables.
What kind of other solution is out there?
You can still use key value coding methods on your custom class, as long as you name your variables appropriately there's no difference there. With that being said though, when I'm working with XML I usually end up testing each node name or creating a key lookup table, since the names in the data source I'm working with aren't key value coding compliant. If you have control over the data source though, you could just continue to use setValue:forKey:.
I'd recommend reading this guide about key value coding if you haven't already. It's fundamental to many great tools in Cocoa.
Look into NSCoding. You can use the NSCoding protocol to save your object, properties and all, as data.
Once your object is NSCoding compliant, you can just archive the whole array of objects using NSKeyedArchiver.
Please note that if you have a large number of objects, this can dramatically affect the app's performance on the iPhone during load and save.