33

Im trying building my application from Xcode11 beta on phone IOS 13 Beta. I have crash when application loading.

2019-07-22 13:58:12.910460+0300 GoodWine[3738:792501] [error] 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: 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.

2019-07-22 13:58:12.910595+0300 GoodWine[3738:792501] [error] 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.

CoreData: warning: Property 'value' on Entity 'SFMCKeyValueEntity' is using nil or an insecure NSValueTransformer. Please switch to using "NSSecureUnarchiveFromData" or a subclass of NSSecureUnarchiveFromDataTransformer instead.

Prince Vegeta
  • 719
  • 6
  • 21
  • 5
    The most significant information is ***Please switch to using "NSSecureUnarchiveFromData" or a subclass of NSSecureUnarchiveFromDataTransformer instead***. – vadian Jul 22 '19 at 12:37
  • 1
  • I just ran into this error myself and found the below answer. When I inspected the Entity properties I saw that property 'Class' had a default value of 'Global namespace' in the field. I switched that to 'Current Product Module' and re-ran the program and the errors disappeared. I'll keep an eye on it and if the errors come back I'll try the answer below. – SouthernYankee65 Jun 25 '20 at 14:08

2 Answers2

42

I found this solution. The errors have disappeared and it would seem to work. I keep testing.

For all Transformable attributes, I have set “Transformer” to “NSSecureUnarchiveFromData” in the Data Model Inspector panel.

enter image description here

EDIT:

After a few days of testing I add something to my previous solution.

The previous solution works if, after the changes, the application is deleted. Otherwise, the data model is not recognized and is created from scratch, losing all the historical information (and in production this is not acceptable!!!).

The final solution I adopted was to add these changes to a new model (following this link) and implementing the migration (always described in the link).

In this case the warning appears only once after the update and then disappears.

Isuru
  • 30,617
  • 60
  • 187
  • 303
SirOz
  • 461
  • 3
  • 6
  • 1
    I tried to follow your suggestion: In my Transformable Attribute, I set as Transformer `NSSecureUnarchiveFromData`, deleted the app, cleaned the project, and recompiled. I got a new error saying something like (cannot reproduce, see below) my class does not adopt the required protocol. Since there seems to be **no** documentation on `NSSecureUnarchiveFromData`, I switched back to setting Transformer to `nil`, deleted the app and cleaned the project, and since then, the error does no longer appear in the logs. Very strange... – Reinhard Männer Sep 22 '19 at 20:05
  • @ReinhardMänner thank god for your message, did the exact same thing, fixed everything – erotsppa Feb 15 '20 at 06:04
  • Can confirm on the edited solution, I had to create a new data model in order for this to work. – Jared Nov 05 '20 at 00:48
9

My solution was to stay with old default transformers in order to avoid any compatibility issues. The issues may arise since default (nil) transformers will be replaced with NSSecureUnarchiveFromData eventually, I'm not sure if previously persisted values would be decoded properly (they were encoded by default transformer but after the update they will be decoded by NSSecureUnarchiveFromDataTransformer). I've implemented an explicit default transformer for fields of NSDictionary, NSArray, NSSet foundation types that comply to NSCoding out of the box:

@objc(DefaultTransformer)
class DefaultTransformer: ValueTransformer {
    override class func transformedValueClass() -> AnyClass {
        return NSData.self
    }

    override open func reverseTransformedValue(_ value: Any?) -> Any? {
        guard let value = value as? Data else {
            return nil
        }
        return NSKeyedUnarchiver.unarchiveObject(with: value)
    }

    override class func allowsReverseTransformation() -> Bool {
        return true
    }

    override func transformedValue(_ value: Any?) -> Any? {
        guard let value = value else {
            return nil
        }
        return NSKeyedArchiver.archivedData(withRootObject: value)
    }
}

For my special datatypes that comply NSCoding I've implemented particular transformers as follows:

@objc(EmailTransformer)
class EmailTransformer: ValueTransformer {
    override class func transformedValueClass() -> AnyClass {
        return NSData.self
    }

    override open func reverseTransformedValue(_ value: Any?) -> Any? {
        guard let value = value as? Data else {
            return nil
        }
        return NSKeyedUnarchiver.unarchiveObject(with: value)
    }

    override class func allowsReverseTransformation() -> Bool {
        return true
    }

    override func transformedValue(_ value: Any?) -> Any? {
        guard let value = value as? [Email] else {
            return nil
        }
        return NSKeyedArchiver.archivedData(withRootObject: value)
    }
}

After that, I set these transformers for the transformable fields, thus explicitly opted the safest way. Pros of the solution: you don't need to bother with data migration, just implement explicit transformers and set them to any data model version you already have.

kas-kad
  • 3,736
  • 1
  • 26
  • 45
  • The EmailTransformer looks exactly as your DefaultTransformer. Is that intended? – Wizard of Kneup Oct 17 '19 at 08:26
  • @WizardofKneup it is different a bit – kas-kad Oct 17 '19 at 12:01
  • it's a bit of a search game, but I did find it now. :-) – Wizard of Kneup Oct 18 '19 at 15:47
  • I believe this could cause issues in the future given what the error message says at the very end: "transformable properties containing classes that do not support NSSecureCoding will become unreadable" – zath Jan 31 '20 at 10:04
  • @zath In my case I store NSData, it is NSSecureCoding-compliant. Thus I think I'm on the safe side. – kas-kad Jan 31 '20 at 14:04
  • @kas-kad Yes you're probably right! I misread the error message slightly :) I thought they were talking about the transformers, rather than the transformable properties themselves. – zath Jan 31 '20 at 14:21