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

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.

Related

when to use transformable data type versus relationship core data

This is a newbie type question, but I am stuck on how to do this within the context of Core Data in iOS.
I have a data type I want to use called Measurement which consists of a unit (string) and a value (double). I have another class PhysicalAttributes which has a number of attributes some of which are primitive data types and some (most) which should be of type Measurement.
In Core Data, I made an entity called Measurement and an entity called PhysicalAttributes.
If I were not using Core Data, I would have a class like:
#interface PhysicalAttributes : NSObject
#property (nonatomic) Measurement *height ;
#property (nonatomic) Measurement *weight ;
// etc.
#end
But I cannot determine if in Core Data I should use relationships called height, weight, etc. or use a transformable data type and model it that way. It doesn't feel right to call it a relationship since Measurement is really a data type.
All the examples I can find of using core data don't really give examples of something like the above.
Any help/pointers appreciated!
Do you really want Measurement? Maybe as an abstract class or a protocol, but you probably want classes for Weight and Height, otherwise, the possible types inside Measurement are going to get really ugly.
I agree with you about it making you feel dirty to use a relationship for something like this, but, the other way to look at it is these measurements are probably being captured at some point in time, so you could add a timestamp too.
Martin Fowler's book Analysis Patterns discusses this at some length and comes down on the side of doing classes (which is correct) for these things.

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

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.

Custom UID data type for CoreData

The CoreData documentation says "You can sometimes benefit from creating your own unique ID (UUID) property which can be defined and set for newly inserted objects. This allows you to efficiently locate specific objects using predicates (though before a save operation new objects can be found only in their original context)."
What should be used for this type?
A managed object's objectID is usually 'NSManagedObjectID' type but the DataModel wizard tool via XCode that allows you to set the type for a given attribute only has the basic allowed types in addition to 'Undefined', Binary Data, & Transformable.
If I wanted to have an attribute that serves as a secondary id for an object (in addition to it's standard ObjectID), do you store it as an NSString or would you custom modify the object model to hold NSManagedObjectID?
(for iPhone app/CoreData development)
An NSString or integer attribute are logical choices, though you could use a transformable attribute to store anything you wanted (that could be appropriately serialized, of course). An incrementing integer is probably good enough for many uses, but each use case is different. Many algorithms exist on the net for generating string or byte-array UUIDs (start with Google). An NSString UUID is quite easy:
+(NSString*)UUIDString {
CFUUIDRef theUUID = CFUUIDCreate(NULL);
CFStringRef string = CFUUIDCreateString(NULL, theUUID);
CFRelease(theUUID);
return [NSMakeCollectable(string) autorelease];
}
for an array of bytes, look at CFUUIDGetUUIDBytes().
Before you go this route, think long and hard about whether it is necessary. Folks coming from a SQL point of view "want" their ids, but Core Data is not about relational databases. It's an object graph management framework that just happens to use SQLite as one backing implementation. If you're trying to do SQL-like things in Core Data, you're going to be fighting the framework. There's often a way around needing a separate id property in proper usage of the Core Data framework.

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.