简体   繁体   English

如何修复“NSKeyedUnarchiveFromData”不应该用于取消归档并将在未来版本中删除的错误?

[英]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.我正在使用 Core Data 进行持久存储,但出现下面列出的错误。 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.我试图遵守 NSSecureCoding 协议的尝试失败了。 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.我发布我的原始代码是因为我认为从头开始尝试解决问题可能比尝试修复我在 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 'NSKeyedUnarchiveFromData' 不应用于取消归档,并将在未来版本中删除

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.SelectedImage类进行更改。
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.创建SelectedImageTransformer类。
@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.按如下方式编辑 CoreData 模型。

在此处输入图片说明

  1. Call the register method in AppDelegate (if you use the UIKit) before initializing the persistent container.在初始化持久容器之前调用AppDelegate 中的 register 方法(如果您使用 UIKit)。
// 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.有关更多详细信息,您可以阅读这篇这篇文章。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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