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.
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.
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.
I have a list of objects that can sometimes change, and I want to keep a persistent cache on the device whenever the app is closed or move to the background.
Most of the objects in the list will not change, so i was wondering what is the best way to save the list. I have two major options i think about:
Using NSKeyedArchiver / unArchiver - This is the most convenient method, because the objects i'm serializing hold other custom objects, so this way i can just write a custom encode method for each of them. The major problem is that i didn't find on Google how to serialize only the changed objects, and serializing the entire list every time seems very wasteful.
Using SQLite - this is what i'm currently using, and the worst problem here is that adding \ changing properties of the objects is very complicated, and much less elegant.
Is there any way that i can enjoy the convenience of NSKeyedArchiver but only serialize the changed objects?
Like Adam Ko I would suggest using Core Data:
This kind of problem is what it's really good at, after all!
If your cache items are independent from each other, this could be achieved by simply wrapping your cache-items by a thin layer of NSManagedObject (i.e. you could benefit from Core Data with only minor changes to your app).
This wrapper entity could store an archived version of a cache item in an attribute of type NSBinaryDataAttributeType and provide access to the unarchived object through a transient property.
See Non-Standard Persistent Attributes for an example.
I have an image field of type transformable and a typical ImageToDataTransformer class. 99% of the time that's perfect and great shortcut, but just occasionally I find myself transforming the managed object back to NSData (knowing that if it wasn't for the ImageToDataTransformer I would have got NSData in the first place). As these operations are fairly expensive on an iPhone, is there a way of avoiding the transformer on the rare occasions I just want the NSdata ?
Use the transformable attribute, but no transformer. Then, handle the transformation manually.
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.