swift - 编码/解码 UIBezierPath 到 CoreData 问题
问题描述
我将 UIBezierPaths 存储在 CoreData 中。为此,我必须将字段的类型设置为数据;我无法让 Transformable 工作,但确实如此。
但是,当我检索或存储这些路径时,在编码/解码过程中会出现错误。错误是
2021-11-02 09:08:39.138674+0700 TestSVG[82461:1408543] [general] 'NSKeyedUnarchiveFromData' should not be used to for un-archiving and will be removed in a future release
我根据此处提供的帮助使用的方法是:
func bezierToData(path: UIBezierPath) -> Data? {
do {
return try NSKeyedArchiver.archivedData(withRootObject: path, requiringSecureCoding: false)
} catch {
return nil
}
}
func dataToBezier(src: Data) -> UIBezierPath? {
do {
return try NSKeyedUnarchiver.unarchivedObject(ofClass: UIBezierPath.self, from: src)!
} catch {
return nil
}
}
这似乎是苹果公司强加的多项改变。我的需求很简单,我正在做的事情很完美,但我当然不想遇到未来的问题。
这个答案:'NSKeyedUnarchiveFromData' 不应该用于取消归档,并且将在未来的版本中删除,适用于可存储为可转换的对象,我无法正常工作。同样,这里的建议是使用 Data 并且已经奏效。
我已经在这里和其他地方阅读了所有我能找到的答案,因为基本上,StackOverflow 通常会优先考虑在提出问题后立即接受的答案,并且当接受的答案过时时没有更新方法......它可能是一个燃烧的垃圾箱在获得相关答案时会感到困惑,至少对于像 moi 这样的相对新手而言。
但我离题了。谁能指出我当前的做法,这将允许我简单地将 UIBezierPaths 序列化和反序列化到 CoreData 存储中?
解决方案
我已经尝试过了,它成功地进行了编码和解码。没有关于过时功能的警告。
这应该适用于Binary Data
func bezierToData(path: UIBezierPath) -> Data? {
try? NSKeyedArchiver.archivedData(withRootObject: path, requiringSecureCoding: true)
}
func dataToBezier(src: Data) -> UIBezierPath? {
try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(src) as? UIBezierPath
}
let path = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: 100, height: 200), cornerRadius: 10)
let pathData = bezierToData(path: path)
let unarchivedPath = dataToBezier(src: pathData!)
另一种选择是创建Transformable
字段并NSSecureUnarchiveFromDataTransformer
在其中使用。不要忘记在 CoreData 数据模型检查器中设置这个 Transformer(并且Custom class
是)。UIBeizerPath
import UIKit
class UIBezierPathToDataTransformer: NSSecureUnarchiveFromDataTransformer {
override class func allowsReverseTransformation() -> Bool {
return true
}
override class func transformedValueClass() -> AnyClass {
return UIBezierPath.self
}
override class var allowedTopLevelClasses: [AnyClass] {
return [UIBezierPath.self]
}
override func transformedValue(_ value: Any?) -> Any? {
guard let data = value as? Data else {
fatalError("Wrong data type: value must be a Data object; received \(type(of: value))")
}
return super.transformedValue(data)
}
override func reverseTransformedValue(_ value: Any?) -> Any? {
guard let path = value as? UIBezierPath else {
fatalError("Wrong data type: value must be a UIBezierPath object; received \(type(of: value))")
}
return super.reverseTransformedValue(path)
}
}
extension NSValueTransformerName {
static let uiBezierPathToDataTransformer = NSValueTransformerName(rawValue: "UIBezierPathDataTransformer")
}
此外,当将此添加到您创建持久容器的位置(可能在 AppDelegate 中)时:
lazy var persistentContainer: NSPersistentContainer = {
// Register the transformer at the very beginning.
ValueTransformer.setValueTransformer(UIBezierPathToDataTransformer(), forName: .uiBezierPathToDataTransformer) // <- HERE
let container = NSPersistentContainer(name: "CoreDataAttributes")
container.loadPersistentStores(completionHandler: { (_, error) in
guard let error = error as NSError? else { return }
fatalError("###\(#function): Failed to load persistent stores:\(error)")
})
container.viewContext.automaticallyMergesChangesFromParent = true
SampleData.generateSampleDataIfNeeded(context: container.newBackgroundContext())
return container
}()
推荐阅读
- java - 如何在 log4j 版本 2 中动态设置 FileAppender 的文件名?
- spring-saml - 实现动态SP、IDP
- php - 如何使用 LOAD INFILE 更新表?
- java - JavaFX 9 @font-face css 不适用于运行时
- adyen - Adyen MarketPay 支持的国家/地区?
- android - 某些 Android 版本的 Firebase 消息传递奇怪行为
- typescript - 在多个组件中共享模型
- c# - 带有表情符号按钮的自定义条目渲染器 (Keyboard.Chat)
- vespa - 如何监控 Vespa 索引磁盘的使用情况和索引文档的数量
- ios - 获取 2 点纬度之间的旅行时间,长 Swift google api