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.
Related
Hi I'm currently trying to set up core data in my project after previously using NSCoding.
I have the problem that I can't save a Set into Core Data. I've looked for days on ways to convert it to Binary data in Swift and saving that but I can't seem to find anything.
The set contains elements of a custom object I made.
PS: If possible, also, how would a generic be saved into Core Data?
Swift sets are bridged to the foundation class NSSet, and NSSet conforms to the NSCoding protocol. That means you can save a set as an attribute of a managed object if you
Treat the set as an NSSet (if it's not one already, use mySet as NSSet)
Adopt NSCoding on your custom objects in the set
Make the Core Data attribute type "transformable"
If you do all that, Core Data will automatically invoke NSCoding methods on the set, which will in turn invoke the same methods on your custom objects. You'll just assign the set to the attribute, and Core Data will do the rest.
I have to store a collection of custom objects (Dictonary) in Core Data Database.
So far so good. The Dictonary is stored and can be loaded without problems as a "Transformable" object.
The custom Object holds properties, but these are nil after loading them from the Database.
After searching a lot, I haven't found anything for this problem.
It seems that the properties are not getting stored in this way. (Maybe because only the address is stored and not the data??)
Sure it would be better to store an object of Core Data supported datatypes, but in this case the transformable Object is just fine and saves me a lot work and time.
Thank U!
The whole idea of transformable objects is covered in the Core Data Guide. Note that this uses a keyed archiver / unarchiver to create a NSData object from your object or the reverse. This means your customer objects my adhere to NSCoding, and encode all the information in them when asked to as well as handle unencoding.
If your are not doing this now this is the root cause of your problem. What I suggest you do is adopt NSCoding in one custom object, then verify that in fact you can encode it to a NSData object, then from the object unencode it and get the same object back. When you have that working you can then test with Core Data.
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.
I have an entity in core data called Location. Inside this I have a few fields, such as date. But, I would also like to save a class object in it that I created called Annotation. What type of attribute would I use for this, since it is a custom class object that I created?
Location (object)
|__ Date
|__ Annotation (MKAnnotation protocol)
You have two options:
If your Annotation class conforms to the NSCoding protocol (or if you're willing to write an NSValueTransformer to convert your custom class to an NSData instance, you can use a transformable attribute in your Core Data entity. Core Data will use the designated NSValueTransformer to automatically serialize/deserialize your Annotation instance for you.
You can create an Annotation entity in your Core Data model. You'll have to write your own code to assign a CLLocationCoordinate2D to the entity. You would probably create a persistent backing using two doubles and then write setters/accessors for the CLLocationCoordinate2D.
The advantage of (1) is that it's easier (if your class conforms to NSCoding). The advantage of (2) is that you can query against the data within the entity, even if using SQLite persistent stores. If you use (1), the data is opaque to the SQLite query engine, so you won't be able to query against it with a SQLite backend.
it would be easier to add the class as a core data class then you could just have a relationship between the two classes as a one-to-one relation. you can however use the type binary data as an attribute type and store whatever data you want in there. ( i use this to store c structs sometimes ) You just need to use the NSData class to wrap your object and set the property.
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.