简体   繁体   中英

How to fix the ''NSKeyedUnarchiveFromData' should not be used to for un-archiving and will be removed in a future release' error?

I am using Core Data for persistent storage and I am getting the error listed below. I have looked up the message and I know it has something to do with the fact that I am using the transformable and a custom class. Despite my research I am not sure how to fix it. My attempt at conforming to the NSSecureCoding protocol failed miserably. I am posting my original code because I think it might be easier to try and solve the issue from scratch rather than trying to fix my poor attempt at NSSecureCoding. Thank you in advance! Any help is much appreciated.

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

My Entity: 在此处输入图片说明

My Custom Class:

public class SelectedImages: NSObject, NSCoding {
    public var images: [SelectedImage] = []
    enum Key: String {
        case images = "images"
    }
    init(images: [SelectedImage]) {
        self.images = images
    }
    public func encode(with aCoder: NSCoder) {
        aCoder.encode(images, forKey: Key.images.rawValue)
    }
    public required convenience init?(coder aDecoder: NSCoder) {
        let mImages = aDecoder.decodeObject(forKey: Key.images.rawValue) as! [SelectedImage]
        self.init(images: mImages)
    }
}

public class SelectedImage: NSObject, NSCoding {
    public var location: Int = 0
    public var duration: Int = 10
    public var localIdentifier: String = ""
    
    enum Key: String {
        case location = "location"
        case duration = "duration"
        case localIdentifier = "localIdentifier"
    }
    init(location: Int, duration: Int, localIdentifier: String) {
        self.location = location
        self.duration = duration
        self.localIdentifier = localIdentifier
    }
    public override init() {
        super.init()
    }
    public func encode(with aCoder: NSCoder) {
        aCoder.encode(location, forKey: Key.location.rawValue)
        aCoder.encode(duration, forKey: Key.duration.rawValue)
        aCoder.encode(localIdentifier, forKey: Key.localIdentifier.rawValue)
    }
    public required convenience init?(coder aDecoder: NSCoder) {
        let mlocation = aDecoder.decodeInt32(forKey: Key.location.rawValue)
        let mduration = aDecoder.decodeInt32(forKey: Key.duration.rawValue)
        let mlocalIdentifier = aDecoder.decodeObject(forKey: Key.localIdentifier.rawValue) as! String
        self.init(location: Int(mlocation), duration:Int(mduration), localIdentifier:String(mlocalIdentifier))
    }
}

View Controller:

guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let managedContext = appDelegate.persistentContainer.viewContext
let userEntity = NSEntityDescription.entity(forEntityName: "EntityTest", in: managedContext)!
let selectedImages = NSManagedObject(entity: userEntity, insertInto: managedContext) as! EntityTest
let mImages = SelectedImages(images: selectionArrays)
selectedImages.setValue(mImages, forKeyPath: "image")
        
do {
    try managedContext.save()
    print("Images saved to core data")
} catch let error as NSError {
    print("Could not save. \(error), \(error.userInfo)")
}
    let newViewController = PickerTest6()
    self.navigationController?.pushViewController(newViewController, animated: true)

I haven't run this code, but it should work.

  1. Make changes to the SelectedImage class.
public class SelectedImage: NSObject, NSSecureCoding { // Class must inherit from NSSecureCoding
    public static var supportsSecureCoding: Bool = true // It's the required property
    
    public var location: Int = 0
    public var duration: Int = 10
    public var localIdentifier: String = ""
    
    private enum CodingKeys: String {
        case location, duration, localIdentifier
    }
    
    public override init() {
        super.init()
    }
    
    init(location: Int, duration: Int, localIdentifier: String) {
        self.location = location
        self.duration = duration
        self.localIdentifier = localIdentifier
    }
    
    public required init?(coder: NSCoder) {
        self.location = coder.decodeInteger(forKey: CodingKeys.location.rawValue)
        self.duration = coder.decodeInteger(forKey: CodingKeys.duration.rawValue)
        
        // Now instead of decodeObject(forKey:) you should use decodeObject(of: forKey:).
        self.localIdentifier = coder.decodeObject(of: NSString.self, forKey: CodingKeys.localIdentifier.rawValue) as String? ?? ""
    }
    
    public func encode(with coder: NSCoder) {
        coder.encode(location, forKey: CodingKeys.location.rawValue)
        coder.encode(duration, forKey: CodingKeys.duration.rawValue)
        coder.encode(localIdentifier, forKey: CodingKeys.localIdentifier.rawValue)
    }
}
  1. Create the SelectedImageTransformer class.
@objc(SelectedImageTransformer)
final class SelectedImageTransformer: NSSecureUnarchiveFromDataTransformer {
    static let name = NSValueTransformerName(rawValue: String(describing: SelectedImageTransformer.self))
    
    override class var allowedTopLevelClasses: [AnyClass] {
        return super.allowedTopLevelClasses + [SelectedImage.self]
    }

    public class func register() {
        let transformer = SelectedImageTransformer()
        ValueTransformer.setValueTransformer(transformer, forName: name)
    }
}
  1. Edit the CoreData model as follows.

在此处输入图片说明

  1. Call the register method in AppDelegate (if you use the UIKit) before initializing the persistent container.
// MARK: - Core Data stack
lazy var persistentContainer: NSPersistentContainer = {
    // Register the transformer
    SelectedImageTransformer.register()
    
    let container = NSPersistentContainer(name: "AppName")
    container.loadPersistentStores(completionHandler: { (storeDescription, error) in
        if let error = error as NSError? {
            fatalError("Unresolved error \(error), \(error.userInfo)")
        }
    })
    return container
}()

For more details, you can read this or this article.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM