1

I am using Coredata with Transformable types and getting a lot of this warning:

'NSKeyedUnarchiveFromData' should not be used to for un-archiving and will be removed in a future release

So I tried to make adjustments, this was my custom class before:

public class OurAppInfo: NSObject, NSCoding {
        
    var code: String?
    var value: String?
    var imgUrl: String?
    
    init(code: String, value: String, imgUrl: String) {
        super.init()
        self.code = code
        self.value = value
        self.imgUrl = imgUrl
    }
    
    public func encode(with coder: NSCoder) {
        coder.encode(code, forKey: "code")
        coder.encode(value, forKey: "value")
        coder.encode(imgUrl, forKey: "imgUrl")
    }
    
    
    required public init?(coder: NSCoder) {
        super.init()
        code = coder.decodeObject(forKey: "code") as? String
        value = coder.decodeObject(forKey: "value") as? String
        imgUrl = coder.decodeObject(forKey: "imgUrl") as? String
    }
}

Than I changed it to NSSecureCoding:

public class OurAppInfo: NSObject, NSSecureCoding {
    
    public static var supportsSecureCoding: Bool { get { return true } }
    
    var code: String?
    var value: String?
    var imgUrl: String?
    
    init(code: String, value: String, imgUrl: String) {
        super.init()
        self.code = code
        self.value = value
        self.imgUrl = imgUrl
    }
    
    public func encode(with coder: NSCoder) {
        coder.encode(code, forKey: "code")
        coder.encode(value, forKey: "value")
        coder.encode(imgUrl, forKey: "imgUrl")
    }
    
    required public init?(coder: NSCoder) {
        super.init()
        
        if let decodedCode = coder.decodeObject(of: NSString.self, forKey: "code") {
            code = String(decodedCode)
        }
        
        if let decodedValue = coder.decodeObject(of: NSString.self, forKey: "value") {
            value = String(decodedValue)
        }
        
        if let decodedImgUrl = coder.decodeObject(of: NSString.self, forKey: "imgUrl") {
            imgUrl = String(decodedImgUrl)
        }
    }
}

And inside the NSManagedObject changed Transformer into NSSecureUnarchiveFromData:

enter image description here

When running for the first time everything is ok, but after saving the content and restarting the app, it crashes with this error:

MyApp[35816:2302009] [error] error: SQLCore dispatchRequest: exception handling request: <NSSQLFetchRequestContext: 0x2822e48c0> , The data couldn’t be read because it isn’t in the correct format. with userInfo of {
    NSUnderlyingError = "Error Domain=NSCocoaErrorDomain Code=4864 \"value for key 'NS.objects' was of unexpected class 'MyApp.OurAppInfo (0x1052bcc70) [/private/var/containers/Bundle/Application/21943B4A-FA87-4B41-943E-B79F0ED43A2A/MyApp.app]'. Allowed classes are '{(\n    \"NSNull (0x1e5c03530) [/System/Library/Frameworks/CoreFoundation.framework]\",\n    \"NSArray (0x1e5c02fb8) [/System/Library/Frameworks/CoreFoundation.framework]\",\n    \"NSURL (0x1e5c03b98) [/System/Library/Frameworks/CoreFoundation.framework]\",\n    \"NSString (0x1e5c0df00) [/System/Library/Frameworks/Foundation.framework]\",\n    \"NSDate (0x1e5c03030) [/System/Library/Frameworks/CoreFoundation.framework]\",\n    \"NSNumber (0x1e5c0e658) [/System/Library/Frameworks/Foundation.framework]\",\n    \"NSDictionary (0x1e5c03198) [/System/Library/Frameworks/CoreFoundation.framework]\",\n    \"NSSet (0x1e5c035f8) [/System/Library/Frameworks/CoreFoundation.framework]\",\n    \"NSData (0x1e5c02748) [/System/Library/Frameworks/CoreFoundation.framework]\",\n    \"NSUUID (0x1e5c10070) [/System/Library/Frameworks/Foundation.framework]\"\n)}'.\" UserInfo={NSDebugDescription=value for key 'NS.objects' was of unexpected class 'MyApp.OurAppInfo (0x1052bcc70) [/private/var/containers/Bundle/Application/21943B4A-FA87-4B41-943E-B79F0ED43A2A/MyApp.app]'. Allowed classes are '{(\n    \"NSNull (0x1e5c03530) [/System/Library/Frameworks/CoreFoundation.framework]\",\n    \"NSArray (0x1e5c02fb8) [/System/Library/Frameworks/CoreFoundation.framework]\",\n    \"NSURL (0x1e5c03b98) [/System/Library/Frameworks/CoreFoundation.framework]\",\n    \"NSString (0x1e5c0df00) [/System/Library/Frameworks/Foundation.framework]\",\n    \"NSDate (0x1e5c03030) [/System/Library/Frameworks/CoreFoundation.framework]\",\n    \"NSNumber (0x1e5c0e658) [/System/Library/Frameworks/Foundation.framework]\",\n    \"NSDictionary (0x1e5c03198) [/System/Library/Frameworks/CoreFoundation.framework]\",\n    \"NSSet (0x1e5c035f8) [/System/Library/Frameworks/CoreFoundation.framework]\",\n    \"NSData (0x1e5c02748) [/System/Library/Frameworks/CoreFoundation.framework]\",\n    \"NSUUID (0x1e5c10070) [/System/Library/Frameworks/Foundation.framework]\"\n)}'.}";
}

What am I missing here?

ytpm
  • 4,962
  • 6
  • 56
  • 113
  • Why for whoever's sake do you encode a class with Core Data compliant types rather than using an entity and relationships? – vadian Dec 03 '20 at 12:29
  • There are some several classes which I don't want to create entities for, just save them as object or an array of objects inside coredata managed object. – ytpm Dec 03 '20 at 12:31
  • Then isn't it much more lightweight to encode the objects to JSON? – vadian Dec 03 '20 at 12:34
  • Maybe, I don't really know. That's why I asked a question.. I don't want to store them as an entity, what is the best approach? I do have several of similar classes. Do I have to encode them to JSON and decode them when I need to use them? – ytpm Dec 03 '20 at 12:36
  • You can do the conversion it with a computed property. – vadian Dec 03 '20 at 12:37
  • How can I do that? – ytpm Dec 03 '20 at 12:40
  • There is no way to store this class as a Data object and when I want to use it, just to decode it? – ytpm Dec 03 '20 at 12:41
  • Most likely it's possible but in the Swift world there are patterns with less overhead. In the Core Data model declare the `@NSManaged` property as `String`. Add a computed property `var infoArray : [OurAppInfo]`. In the getter read the string from the property and decode it to the array of `OurAppInfo`. In the setter encode `newValue` to a JSON string and assign it to the `@NSManaged` property – vadian Dec 03 '20 at 14:37
  • The transformer name is optional. Have you tried no transformer name? – Willeke Dec 04 '20 at 14:55

0 Answers0