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

标签 ios swift core-data nssecurecoding transformable

我正在使用 Core Data 进行持久存储,但出现下面列出的错误。我查看了该消息,我知道它与我使用的是可转换类和自定义类有关。尽管我进行了研究,但我不知道如何解决它。我试图遵守 NSSecureCoding 协议(protocol)的尝试失败了。我发布我的原始代码是因为我认为从头开始尝试解决问题可能比尝试修复我在 NSSecureCoding 上的糟糕尝试更容易。先感谢您!任何帮助深表感谢。

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


我的实体:
enter image description here
我的自定义类:
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)

最佳答案

我还没有运行过这段代码,但它应该可以工作。

  • 更改 已选图片 类(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)
        }
    }
    
  • 创建 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)
        }
    }
    
  • 编辑 CoreData 模型,如下所示。

  • enter image description here
  • 调用中的注册方法AppDelegate (如果您使用 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
    }()
    
    更多详情,您可以阅读thisthis文章。

    关于ios - 如何修复 '' NSKeyedUnarchiveFromData' 不应该用于取消归档并将在未来版本中删除的错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64919128/

    相关文章:

    swift - NSAlert() runmodal 此类对于键 modalWindow 不符合键值编码

    ios - 检索未包含在 CoreData 请求结果中的第二天

    ios - 我们可以更改 AlertController 按钮字体吗?

    ios - 如何删除/取消订阅核心蓝牙服务?

    ios - 需要使用 collectionViewCell 的数量自动水平滚动 UICollectionView

    iOS 应用程序提交 - 无效的二进制文件

    ios - 在 UITableViewCell 上设置自定义分隔符

    ios - IQKeyboardManager 与 DownPicker 冲突

    objective-c - NSPrivateQueueConcurrencyType 串行还是并发?

    ios - CloudKit/iCloud - 教师/学生场景