Where to Implement Nsvaluetransformer for Core Data in Swift

Where to implement NSValueTransformer for Core Data in Swift

The "where" is just anywhere in your project. Anywhere that ensures that your NSValueTransformer subclass will exist at run time. Implement the NSValueTransformer subclass, and enter the class name in the Core Data model as the value transformer.

However there is a default transformer. Any class that adopts the NSCoding protocol can be automatically transformed by Core Data. In that case you mark the attribute as transformable but don't include a class name. This includes NSURL, so you don't need to transform that or convert it to a string.

For your NSDocument subclass then, you have the option of either implementing NSCoding in the class or of implementing an NSValueTransformer subclass for the document type.

Secure Coding Measurement Classes in Core Data, NSValueTransformers

Thanks to @LeoDabus I was finally able to hammer this out. The key is to transform the Swift Measurements into NSMeasurement and use NSMeasurement in Core Data. You will need to set your custom class to an NSMeasurement. Your transformer will be a custom value transformer. I called mine NSMeasurementValueTransformer. Your .xcdatamodeld will look like this:

Sample Image
I defined my custom value transformer as:

@objc(NSMeasurementValueTransformer)
final class NSMeasurementValueTransformer: NSSecureUnarchiveFromDataTransformer {
static let name = NSValueTransformerName(rawValue: String(describing: NSMeasurementValueTransformer.self))
override static var allowedTopLevelClasses: [AnyClass] {
return [NSMeasurement.self]
}

public static func register() {
let transformer = NSMeasurementValueTransformer()
ValueTransformer.setValueTransformer(transformer, forName: name)
}
}

Interestingly, I didn't have to register the value transformer. Maybe someone can explain why, but it works without registration.

Lastly, in an extension, I declared a public facing variable that handles the casting of the variable from and to the Measurement I want to use like this:

extension Item {
public var length: Measurement<UnitLength> {
// The getter returns an actual value, not an optional. If you want to return an optional, just use:
// get { length_ as Measurement<UnitLength> }
get { length_ as Measurement<UnitLength>? ?? Measurement(value: 0, unit: UnitLength.meters) }
set { length_ = newValue as NSMeasurement }
}

}

You will notice that the Core Data Attribute is named length_. I can still use Swift Measurements in my app, but store them securely in Core Data. That fixes the Core Data warning:

CoreData: One or more models in this application are using
transformable properties with transformer names that are either unset,
or set to NSKeyedUnarchiveFromDataTransformerName. Please switch to
using “NSSecureUnarchiveFromData” or a subclass of
NSSecureUnarchiveFromDataTransformer instead. At some point, Core Data
will default to using “NSSecureUnarchiveFromData” when nil is
specified, and transformable properties containing classes that do not
support NSSecureCoding will become unreadable.

Core Data : No NSValueTransformer with class name XXX was found for attribute YYYY on entity ZZZZ

I spent way to much time on this to not share the solution I found :

I had to make the NSValueTransformer subclass available to Objc.

@objc(LocationArrayTransformer)
class LocationArrayTransformer : NSValueTransformer {
....
}

Simple as that.


As @Sbooth points out, Swift classes are namespaced. Using @objc makes the class available without namespacing. So setting the transformer name as MyApp.Mytransformer works well too !

iOS Core Data encryption using NSValueTransformer

I finally figured it out... I was confused as to what type very object had to be and what my nsvaluetransformer had to return. I wasnt casting the value to the proper type in the nsvaluetransformer and thus I was returning nil in the code. However it wasnt crashing in a way that I would easily figure this out. Secondly I changed the entity column back to an NSObject. Returned an NSData object in the transformedValue method and a NSString in the reverseTransformedValue method. This was actually all i needed to make it work. Thanks a lot for your help. It indeed was a type error.

Using a system supplied NSValueTransformer on a transformable Core Data attribute

Turns out that the actual string that the NSKeyedUnarchiveFromDataTransformer points too for this transformer is NSKeyedUnarchiveFromData. But even more importantly: if you specify this, the transformer will be used in the wrong direction. Leave the transformer name field empty to use NSKeyedUnarchiveFromDataTransformer correctly.



Related Topics



Leave a reply



Submit