CoreData Transformable Types and SecureCoding

I have a CoreData entity with a transformable property data that stores an NSDictionary. All of the classes inside the dictionary conform to NSSecureCoding

I have been getting many instances of this warning : 'NSKeyedUnarchiveFromData' should not be used to for un-archiving and will be removed in a future release

In trying to clean up the warning and future-proof my app, but I am running into a lot of trouble.

My understanding is that using NSKeyedUnarchiveFromData as the transformer in my data properties attribute should work, since the top level class is a dictionary and all of the contents conform to NSSecureCoding.

However, my data dictionary is now coming back as NSConcreteMutableData so I cannot access the data in it.

I have also tried creating a custom value transformer with additional allowedTopLevelClasses, but that hasn't helped, and again, the topLevel type is an NSDictionary, which should be allowed.

Thank you for any guidance.

Accepted Reply

Thanks. The relevant piece that I was missing is that it's not just the literal topLevelClasses that need to be registered with the NSSecureUnarchiveFromDataTransformer, but also any classes contained in the transformable if it's a collection. Therefore, if my NSDictionary has a custom class inside it, I need to register a subclass of NSSecureUnarchiveFromDataTransformer to allow that class.

@objc
class DataTransformer: NSSecureUnarchiveFromDataTransformer {
 
    static let name = NSValueTransformerName(rawValue: String(describing: DataTransformer.self))

    @objc(registerValueTransformer)
    public static func register() {
         let transformer = DataTransformer()
        print(DataTransformer.allowedTopLevelClasses)
         ValueTransformer.setValueTransformer(transformer, forName: name)
     }
    
    override class var allowedTopLevelClasses: [AnyClass] {
        var topLevelClasses = super.allowedTopLevelClasses
        let myClasses = [MyClass.self, MyOtherClass.self]
        topLevelClasses.append(contentsOf: myClasses)
        return topLevelClasses
    }

}

Replies

You need to add an example of your code.

Easiwriter wrote:

You need to add an example of your code.

Yes, that’d help.

To get you started, check out the example of secure coding in Objective-C in this thread.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thanks. The relevant piece that I was missing is that it's not just the literal topLevelClasses that need to be registered with the NSSecureUnarchiveFromDataTransformer, but also any classes contained in the transformable if it's a collection. Therefore, if my NSDictionary has a custom class inside it, I need to register a subclass of NSSecureUnarchiveFromDataTransformer to allow that class.

@objc
class DataTransformer: NSSecureUnarchiveFromDataTransformer {
 
    static let name = NSValueTransformerName(rawValue: String(describing: DataTransformer.self))

    @objc(registerValueTransformer)
    public static func register() {
         let transformer = DataTransformer()
        print(DataTransformer.allowedTopLevelClasses)
         ValueTransformer.setValueTransformer(transformer, forName: name)
     }
    
    override class var allowedTopLevelClasses: [AnyClass] {
        var topLevelClasses = super.allowedTopLevelClasses
        let myClasses = [MyClass.self, MyOtherClass.self]
        topLevelClasses.append(contentsOf: myClasses)
        return topLevelClasses
    }

}