'Core Data & Xcode 11: Please switch to using "NSSecureUnarchiveFromData" or a subclass of NSSecureUnarchiveFromDataTransformer
Just moved to Xcode 11 and getting the following crash at launch:
CoreData: fault: 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.
CoreData: warning: Property 'color' on Entity 'Group' is using nil or an insecure NSValueTransformer. Please switch to using "NSSecureUnarchiveFromData" or a subclass of NSSecureUnarchiveFromDataTransformer instead.
I'm creating an NSPersistentContainer at launch using the code below:
private let container: NSPersistentContainer = {
let container = NSPersistentContainer(name: "MyApp", managedObjectModel: MyAppModelVersion.current.managedObjectModel())
let storeDescription = NSPersistentStoreDescription(url: getStoreURLWithUserName())
storeDescription.shouldMigrateStoreAutomatically = true
storeDescription.shouldInferMappingModelAutomatically = true
container.persistentStoreDescriptions = [storeDescription]
return container
}()
Error occurs right after this line is executed:
let container = NSPersistentContainer(name: "MyApp", managedObjectModel: MyAppModelVersion.current.managedObjectModel())
I also have a property called 'Colorin aGroup` entity that's transformable:
@NSManaged public var color: UIColor?
@NSManaged public var hexColorValue: String?
Below is how set the property:
public var hexColor: String? {
get {
return self.hexColorValue
}
set {
self.hexColorValue = newValue
if let str = newValue {
self.color = UIColor(hex: str)
}
}
}
This is what the property looks like in Core Data:
I am not sure how to recover from this crash. This was working fine with Xcode 10
Solution 1:[1]
Setting Transformer property to NSSecureUnarchiveFromDataTransformer solved the warning in my case. For this select the attribute & set its transformer type to NSSecureUnarchiveFromDataTransformer & run again by pressing commond+R.
Thanks, Ratneshwar
Solution 2:[2]
Swift 5.4.2
This worked for me.
EDIT Link to the article is here.
- Click on the .xcdatamodeld file in the project navigator
- Click on the Entity that has a Transformable Attribute
- Click on the Transformable Attribute
- Click the 'Show Data Model Inspector' icon
- Enter 'NSSecureUnarchiveFromDataTransformer' in the Transformer field - EDIT Make this 'NSSecureUnarchiveFromData' as of Swift 5.5.2.
Your warnings/errors should go away. If not, try cleaning your build folder and rebuild.
Solution 3:[3]
This is related to a migration from NSCoding to the NSSecureCoding protocol. The default ValueTransformer adopts NSCoding, so the only solution that worked for me was to write my own Transformer that adopts the NSSecureUnarchiveFromDataTransformer protocol.
I should say that my own experience is from trying to define an Attribute with the Transformer type to persist a custom class that adopted NSCoding. I was initially met with a warning similar to the OP's error. I was able to suppress the warning by changing the Transformer field on the attribute to "NSSecureUnarchiveFromData" as others have mentioned, but I then received an error along the lines of:
Not able to save to CoreData. SQLCore dispatchRequest Object of class “ ” not among allowed top level class list... as mentioned here. The suggestion to change the Attribute to a Relationship was undesirable in my case.
More digging came up with this blog post that details the "reason" for all of this, and gives a solution that worked for me. The blog actually uses the case of UIColor in the example, but it works for any custom class as well.
Say you have a CustomClass that you want to store as a Transformable Attribute in some Entity. If you're like me, you may have adopted NSCoding and received the aforementioned error. The solution would be to adopt NSSecureCoding instead and define an NSSecureUnarchiveFromDataTransformer subclass:
@objc(CustomClassValueTransformer)
final class CustomClassValueTransformer: NSSecureUnarchiveFromDataTransformer {
static let name = NSValueTransformerName(rawValue: String(describing: CustomClass.self))
// Make sure `CustomClass` is in the allowed class list,
// AND any other classes that are encoded in `CustomClass`
override static var allowedTopLevelClasses: [AnyClass] {
// for example... yours may look different
return [CustomClass.self, OtherClass.self, NSArray.self, NSValue.self]
}
/// Registers the transformer.
public static func register() {
let transformer = CustomClassValueTransformer()
ValueTransformer.setValueTransformer(transformer, forName: name)
}
}
Then make sure to set the Transformer field on your Attribute to "CustomClassValueTransformer" and the Custom Class field to "CustomClass" and you should be good to go.
Solution 4:[4]
For Objektive-C and iOS 14, the following solution works for UIColor attributes.
- First add a new subclass of
NSSecureUnarchiveFromDataTransformer
@interface ColorValueTransformer : NSSecureUnarchiveFromDataTransformer
Add the following static method to your implementation file:
@implementation ColorValueTransformer+ (NSArray<Class> *)allowedTopLevelClasses {return @[UIColor.class];}@endOpen your data model (e.g. datamodel..xcdatamodeld)
Select the entity and the related attribute which needs the new Transformer
Open the Data Model Inspector
Add the class name (e.g.
ColorValueTransformer) as Transformer to that attributeChange the Custom Class to
UIColorBuild and run…
Solution 5:[5]
For the transformable attribute, you need to set its type in the Custom Class field.
For instance, I have a transformable field which stores an array of numbers and its Custom Class is declared as [Int16]. This is most likely the cause of the crash. And as @vadian mentioned before, you don't need both fields.
After your crash is fixed, you can get rid of the warning by setting the Transformer field to NSSecureUnarchiveFromData (you simply type this into the field)
Solution 6:[6]
I received the same warning messages when updating to Xcode 11, however in my case they are just warnings, but no crash.
In order to work out the best solution, I tried creating a stripped down sample app with just a single entity containing a transformable attribute. But it seems that no matter what I tried I could not reproduce the problem. The I copied the model file from my main app to the demo app, and of course that failed.
So I got to the point where I just had two model files and a simple unit test which does nothing more than open the model and create a persistent store container:
func testDataModels() {
openDataModel(named: "samplemodel")
openDataModel(named: "appmodel")
}
func openDataModel(named name: String) {
print("Opening \(name)")
guard let url = findFile(forResource: name, withExtension: "momd"),
let managedObjectModel = NSManagedObjectModel(contentsOf: url)
else {
XCTFail("Unable to find \(name) data model")
return
}
print(url)
_ = NSPersistentStoreCoordinator(managedObjectModel: managedObjectModel)
}
func findFile(forResource name: String, withExtension ext: String) -> URL? {
if let url = Bundle(for: type(of: self)).url(forResource: name, withExtension: ext) {
return url
}
return Bundle.main.url(forResource: name, withExtension: ext)
}
The appmodel causes the error messsages but the sample model does not. Even when I stripped the appmodel down to a single Entity it continues to generate the errors.
Comparing the contents of the samplemodel with the appmodel (show package contents in Finder), there is a hidden file called .xccurrentversion in the samplemodel but not in the appmodel. The file looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>_XCCurrentVersionName</key>
<string>samplemodel.xcdatamodel</string>
</dict>
</plist>
So I created a similar file for the appmodel and put it in the package folder. Surprisingly, that silences the warning messages! Conversely, deleting the .xccurrentversion file from the samplemodel causes the error messages to be generated. This will allow testing of the problem in isolation.
So this may be a short term fix. In the meantime, I need to work out how to migrate to secure coding.
Solution 7:[7]
Maybe some of these answers are acceptable enough, in my case I went to this post. I hope it will be of much help.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Ratneshwar Singh |
| Solution 2 | |
| Solution 3 | |
| Solution 4 | napIT-Apps |
| Solution 5 | alxlives |
| Solution 6 | |
| Solution 7 | iGhost |

