this article reprinted to http://imenjoe.com/2015/04/10/CoreData-transformable-20150410/there is a need to access nsdictionary in core data in the development process, but in core data attributetype there is no direct support for nsdictionary types, basically some scalar types and Date, binary data, undefined, and transformable types.
The original idea was to convert nsdictionary to NSData and then write the binary data type to core data, then use it to read the NSData from core data and back to Nsdictionary, but think of it as actually quite Trouble, to see if Core Data has better support for this kind of demand, this method is used as a last resort. So after sweeping through the Core Data of the attributetype, and then stared at the transformable this type.
The description of transformable in the Apple developer documentation is:
The idea behind transformable attributes is so you access an attribute as a non-standard type, but behind the scenes Cor E 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.
The idea is to hide the above-mentioned ideas under the transformable so that they can be accessed directly from the non-standard type (nsdictionary in our case) and transparently to the attribute in Core Data. The entire transformation and persistence process is done automatically by Core Data.
This conversion process Core Data requires a transformer instance for the conversion between the non-standard type and nsdata, a transformer instance of the implementation of the abstract class Nsvaluetransform, a class that The effect is to convert a value to another value, this is beyond the scope of this discussion, about Nsvaluetransform can refer to this article.
Use
There are two ways to use the transformable type:
If you are editing in. Xcdatamodeld, select the transformable type in the drop-down menu of type, and fill transformer name in the Name text box of the Attribute property page (if you want to customize transformer If you need to fill it out, or use the Core Data default)
If it is written in code, call Setattributetype: Pass in Nstransformableattributetype as a parameter, and then, if necessary, use Setvaluetransformername: to specify The name of the transformer.
I used the first way, directly selected attribute Type is transformable after the completion. Because the text box for value transformer name is empty, Core Data uses nskeyedunarchivefromdatatransformername as transformer by default. This transformer is actually called Nskeyarchiver to convert the non-standard type. The whole process is probably similar to this:
Nsdictionary-NSData
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:myDictionary];
NSData-Nsdictionary
NSDictionary *dictionary = (NSDictionary*)[NSKeyedUnarchiver unarchiverObjectWithData:data];
Since I want to access the nsdictionary is directly supported by the Nskeyedarchiver to convert, so I do not have a custom transformer, directly with the default transformer can meet my needs.
The next step is to regenerate the entity class, because I use mogenerator to generate, to let Mogenerator in the generated entity class attribute is I want nsdcitionary, then also need in. Xcdatamodeld to Attribute User Info to add an item
Key |
Value |
Attributevalueclassname |
Nsdictionary |
|
Mogenerator the entity class is generated from here to get information, know that this attribute to convert non-standard is nsdictionary, in the generated entity class the corresponding property will be nsdictionary, This allows us to read and write to this property directly in the Nsdictionary type, without the need for a process of transformation and storage at the bottom of the tube.
transformable types can be accessed in addition to the Nsdictionary type, Uicolor, CGRect, and so on, in short, if you can't find the type you want in the standard type provided by Core Data, you can use Transformable for easy and quick access.
Extended
In fact, this problem has been solved, but we have mentioned a custom transformer, here we can also expand on this.
The above mentioned that transformable can access other types of non-standard other than nsdictionary, such as Color, Image, but if used by the default transformer, then this Non-standa Rd must implement the Nscoding protocol to serialize its instance to NSData and access it. The reason why I use the default transformer directly is because Nsdictionary implements the Nscoding protocol. But not all non-standard types implement the Nscoding protocol, what about accessing these types of implementations that do not implement the Nscoding protocol?
This is the time to customize the transformer appearances, mentioned above transformer is actually nsvaluetransform abstract class implementation of an example, and this class is the role of a value according to the specified rules to convert to another value, So we can implement nsvaluetransform to specify rules and create instances to complete our custom transformer.
About custom transformer is described in the Apple developer Documentation:
If you specify a custom transformer, it must transform an instance of the non-standard data type into an instance of Nsdat A and support reverse transformation.
If you just need a one-way conversion, you only need to implement these methods:
+ (Class) transformedValueClass;+ (BOOL) allowsReverseTransformation;- (id) transformedValue:(id)value;
If you also want to support reverse conversions, then you need to implement this method:
- (id)reverseTransformedValue:(id)value;
Since Core Data transformable is required to support bidirectional conversions (from non-standard type to NSData, and from NSData to non-standard type), the methods above are implemented, and the following are my web-based two Example (So and Eugene ' s blog) is an example of a transformation:
#import<UIKit/UIKit.h>@interfaceUiimagetonsdatatransformer:Nsvaluetransformer {}@end#import"UIImageToNSDataTransformer.h"@implementationuiimagetonsdatatransformer+ (Class) Transformedvalueclass {return [NSData class]; }+ (BOOL) Allowsreversetransformation {return yes;} -(id) transformedvalue: (id) value {if (value = = Span class= "literal" >nil) return nil; //I pass in raw data when generating the image, save this directly to the database if ([Value Iskindofclass:[nsdata class]]) return value; return uiimagepngrepresentation ((UIImage *) value);} -(id) reversetransformedvalue: (id) value{ return [uiimage imagewithdata: (nsdata *) value];} @end
After realizing the nsvaluetransform, the last thing to do is to fill in the Name text box with this custom transformer class name in the property page of the. Xcdatamodeld transformable attribute.
The custom transformer can also be used to derive another application, which is the ability to encrypt/decrypt one of the attribute in an entity, using a custom encryption/decryption algorithm. Encrypting/Decrypting a attribute alone avoids encrypting/decrypting the entire entity or even the entire database, improving performance and reducing memory consumption. This is explained in the answer to so.
(Note: For the use of Nsvaluetransform, the Nsvaluetransformer +mtlpredefinedtransformeradditions in the mantle library, Mtlvaluetransformer There are good examples of such classes, as well as MATTT's Transformerkit library. )
accessing transformable types of data in Core data