Ada*_*fer 10 core-data ios nssecurecoding ios13
在 iOS 12 中,Apple 引入了NSSecureUnarchiveFromDataTransformerName用于 CoreData 模型实体的可转换属性。我曾经将 Transformer Name 字段保持为空,它隐式使用了NSKeyedUnarchiveFromDataTransformerName. 这个转换器现在已被弃用,将来保持该字段为空将意味着NSSecureUnarchiveFromDataTransformerName取而代之。
在 iOS 13 中,如果该字段为空,您现在会收到一个运行时警告,告诉您上述内容。我在任何地方都找不到关于此的任何文档,我得到的唯一参考是 WWDC 2018 核心数据最佳实践演讲,其中简要提到了我刚才所说的内容。
现在我有一个带有实体的模型,该实体直接将HTTPURLResponse对象存储在 Transformable 属性中。它符合NSSecureCoding,我在运行时检查supportsSecureCoding是true。
NSSecureUnarchiveFromDataTransformerNameTransformer Name 的设置崩溃并显示以下消息:
Object of class NSHTTPURLResponse is not among allowed top level class list (
NSArray,
NSDictionary,
NSSet,
NSString,
NSNumber,
NSDate,
NSData,
NSURL,
NSUUID,
NSNull
) with userInfo of (null)
Run Code Online (Sandbox Code Playgroud)
所以听起来 Transformable 属性只能是这些顶级对象。
我尝试对安全转换器进行子类化并allowedTopLevelClasses按照文档的建议覆盖该属性:
@available(iOS 12.0, *)
public class NSSecureUnarchiveHTTPURLResponseFromDataTransformer: NSSecureUnarchiveFromDataTransformer {
override public class var allowedTopLevelClasses: [AnyClass] {
return [HTTPURLResponse.self]
}
}
Run Code Online (Sandbox Code Playgroud)
然后我想我可以创建一个自定义转换器名称,在模型中设置它并调用setValueTransformer(_:forName:)该名称,但是我找不到 API 来NSKeyedUnarchiveFromDataTransformer为我的自定义名称设置默认值,以防我在 iOS 11 上。
请记住,我使用的是 Xcode 11 Beta 5,但是如果我要接受我得到的错误含义,这似乎无关紧要。
欣赏任何想法。
我编写了一个简单的模板类,它可以轻松地为任何实现NSSecureCoding. 它在 iOS 12 和 13 中对我来说工作得很好,至少在我用作UIColor可转换属性的简单测试中是这样。
使用它(UIColor作为示例):
// Make UIColor adopt ValueTransforming
extension UIColor: ValueTransforming {
static var valueTransformerName: NSValueTransformerName {
.init("UIColorValueTransformer")
}
}
// Register the transformer somewhere early in app startup.
NSSecureCodingValueTransformer<UIColor>.registerTransformer()
Run Code Online (Sandbox Code Playgroud)
核心数据模型中使用的转换器的名称是UIColorValueTransformer。
import Foundation
public protocol ValueTransforming: NSSecureCoding {
static var valueTransformerName: NSValueTransformerName { get }
}
public class NSSecureCodingValueTransformer<T: NSSecureCoding & NSObject>: ValueTransformer {
public override class func transformedValueClass() -> AnyClass { T.self }
public override class func allowsReverseTransformation() -> Bool { true }
public override func transformedValue(_ value: Any?) -> Any? {
guard let value = value as? T else { return nil }
return try? NSKeyedArchiver.archivedData(withRootObject: value, requiringSecureCoding: true)
}
public override func reverseTransformedValue(_ value: Any?) -> Any? {
guard let data = value as? NSData else { return nil }
let result = try? NSKeyedUnarchiver.unarchivedObject(
ofClass: T.self,
from: data as Data
)
return result
}
/// Registers the transformer by calling `ValueTransformer.setValueTransformer(_:forName:)`.
public static func registerTransformer() {
let transformer = NSSecureCodingValueTransformer<T>()
ValueTransformer.setValueTransformer(transformer, forName: T.valueTransformerName)
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2498 次 |
| 最近记录: |