I would like to add a NSDictionary into a NSManagedObject Category class (or the NSManagedObject class itself)
When I do this, and I try to access the property, an exception is thrown.
Is this actually possible? I can't add this property as transient in the model because there is no NSDictionary Data Type, of course.
Thanks!
You don't say how you have currently created the property or what the exception is, but from the description you give it sounds like you should be setting the attribute in the Core Data model to be transformable. Setting it to be transformable will cause the NSDictionary to be archived (and unarchived) as you use it using the standard NSCoding protocol. Be sure that everything you put into the dictionary supports the NSCoding protocol so that it is properly archived and restored.
Using transformable is the way. Below are few more insights on the transformable property.
The Transformable data type is a special data type that allows us to
create attributes based on an Objective-C class (custom objects). This
data type is heavily used for storing instances of UIImage, UIColor,
and so on. As the information stored in the persistent store has to be
in the form of NSData instance, while using Transformable data type,
we need to create Value Transformers to convert the custom object
(information in attribute of Transformable data type) into an instance
of NSData (before storing in the persistent store) and to convert the
instance of NSData back to custom object while retrieving from the
persistent store.
Related
I declared two attributes (currentTime and fullTime) as Transformable in data model as shown below.
How to save data in this attribute? Do I need to convert to NSData first? or any other way?
Transformable need to be convertible to NSData. When you're using a type that conforms to the NSCoding protocol, that happens automatically. When you're not (as with CMTime), you can't use a transformable unless you create your own custom transformer by subclassing NSValueTransformer.
You may find it easier to simply save the CMTime properties in Core Data and reconstruct the CMTime from those. The properties are all numeric types that Core Data knows how to handle.
How would you be able to save a custom object to NSUserDefaults??
NSUserDefaults.standardUserDefaults().setObject(obj, forKey: "object")
NSUserDefaults.standardUserDefaults().synchronize()
The object is of the SPTAuthViewController class in the Spotify iOS SDK, so I can't edit it to add encoder and decoder methods. How can I encode the object into an NSData object to store it in NSUserDefaults?
You can't store custom objects into user defaults. You can only store "property list objects" (NSString, NSData, NSDate, NSNumber, NSArray, or NSDictionary objects).
In order to save a custom object to user defaults you have to convert it to one of those types.
You can make your custom object conform to the NSCoding protocol. To do that you have to implement the init(coder:) and encode(coder:) methods. (I believe that's the swift form of the method names - I've been working in Objective-C lately so my Swift is getting rusty.) How you implement those methods depends on your class. Typically you make multiple calls to encodeObject:forKey: to encode your object's properties.
Once your custom object conforms to NSCoding you can convert it to NSData using the NSKeyedArchiver method archivedDataWithRootObject(). You then convert it from NSData back to the original object using the NSKeyedUnarchiver method unarchiveObjectWithData().
EDIT:
I just realized that you were trying to save a view controller object (SPTAuthViewController to user defaults. You should not serialize and save view controller objects. Controller objects should not be used to save application data.
I have an object which inherits from NSObject & I wish to save it in CoreData, I have already create an attribute of type "Transformable" (which is "id"), so I cannot save the project directly when adding it to the database, for example:
item.idObject = object;
it will generate an error, I think the problem is that I should transform object into id,
how can I do this?
You're on the right track by setting the attribute to transformable. But what you also have to to is to write a valueTransformer for this object that Core Data can use.
There is more in the Documentation
when you assign a core data property, it may only be of certain types, NSString, NSNumber etc... if you assign a relationship, it must be another NSManagedObject instance, if you want to save it as part of the model, you can of course have transient properties of any type.
so...
#implimentation OurClass
#dynamic someProperty; // core data model property NSNumber, NSString, etc.
#dynamic someRelationship; // core data relationship some other subclass of NSManagedObject
#synthesized someOtherProperty; // can be anything, following normal Objective-C semantics.
#end
I want to create a core data model. I have a pameter of type
CFUUIDRef
How will I represent this object in coredata model? I can see only basic types in cdatamodelling screen.
How can I do this with coredata?
You would have to use a string or binary data type in your model and NSManagedObject subclass. Then use the CFUUID methods CFUUIDGetUUIDBytes and CFUUIDCreateFromUUIDBytes whenever you need to set / retrieve the value.
If I understand correctly, the idea behind Core Data transformable attributes is:
implement an NSValueTransformer subclass with returns [NSData
class] in +transformedValueClass along with its implementation
for transformation
register the transformer in +load or +initialize
set an entity's attribute as transformable
set a name for your transformer (the name you used to register it)
in the xcode model editor for the attribute.
At this point, I'd expect that accessing or setting the attribute in a managedObject of the appropriate entity type would trigger the value transformer. However, I'm testing this in an app that uses AFIncrementalStore and I get the following behavior:
A - registering the transformer in +load or +initialize doesn't
seem necessary; Core Data finds it anyway (though read ahead).
B - fetch requests via AFIncrementalStore do trigger the
transformer. For example, I get JSON back from a fetch request and
when mapping the response dictionary to the managedObject, the
transformer is triggered and coverts the appropriate dictionary key
to NSData in the object.
C - HOWEVER, if I try to set or get the attribute via code, the
transformer is not called. That is doing something like
myManagedObject.myAttribute = #"hello" does not trigger the
conversion from NSString to NSData and neither does NSString
*myString = myManagedObject.myAttribute trigger the conversion from NSData to NSString.
So what am I missing? I thought the idea was that CoreData would automatically call the transformer. Am I wrong?
According to this question: Why is my transformable Core Data attribute not using my custom NSValueTransformer?
this seems to be a bug in the Apple frameworks. But what throws me off is that via AFIncrementalStore the value transformer does get called. Maybe the key is that by setting just an attribute via code I am not really triggering AFIncrementalStore and so the change is merely in-memory ?
(From the comment above:) The inverse transformer is called when you save the context,
not when you set an attribute.