Swift Codable:标记对象以进行状态恢复
Posted
技术标签:
【中文标题】Swift Codable:标记对象以进行状态恢复【英文标题】:Swift Codable: marking an object to work with state restoration 【发布时间】:2020-08-15 19:13:32 【问题描述】:我有一个 Swift 类,它存储当前应用于我的视图控制器的不同类型的过滤器。我想使用状态恢复来保存它,这样如果用户离开应用程序并返回,即使应用程序被系统终止,过滤器也会恢复。
我不确定最好的方法是什么。我相信这与Codable
有关,但如何使用 UIViewController 编码/解码使其工作。
首先,类:
@objcMembers class CJDataViewControllerFilters: NSObject
var selectedDateFilters = [String: Array<Date>]()
var selectedTitleFilters = [NSManagedObject]()
var customFilterPredicate: NSPredicate?
var customFilterName: String?
let filterStyle: SectionStyle
init(style: SectionStyle)
self.filterStyle = style
super.init()
UIViewController(仍在 Objective-C 中):
@interface DiaryViewController : UIViewController
@property (nonatomic, strong) CJDataViewControllerFilters *dataFilters;
并调用状态恢复:
- (void)encodeRestorableStateWithCoder:(NSCoder *)coder
[super encodeRestorableStateWithCoder:coder];
[coder encodeObject:self.dataFilters forKey: @"DataFiltersDiary"];
当应用程序进入后台时,这样做会崩溃:
2020-08-15 11:37:55.470081-0700 CJournal[11367:6382501] -[XYZApp.CJDataViewControllerFilters encodeWithCoder:]:无法识别的选择器发送到实例 0x6000014cb640
所以我在CJDataViewControllerFilters
类中添加了Codable
作为协议,并添加了基本一致性:
@objcMembers class CJDataViewControllerFilters: NSObject, Codable
func encode(to encoder: Encoder) throws
print("CJDataViewControllerFilters: encode")
required init(from decoder: Decoder) throws
print("init(from decoder)")
由于同样的原因它仍然崩溃。
如何最好地解决这个问题?有不同的实现方法吗?另外,如何手动编码/解码诸如 NSPreciate 和 NSManagedObjects 数组之类的东西?
Codable
上的大多数示例都涉及 JSON 编码/编码,我在这里不需要(我认为),因此希望得到答复。
【问题讨论】:
【参考方案1】:编码和解码 NSObject 的方法是使其符合 NSCoding(现在,NSSecureCoding)。现在您可以使用键控存档器在保存时将其放入编码器,并使用键控解压缩器在恢复时将其从编码器中取出。
NSPredicate 等大部分内置类型已经符合 NSSecureCoding,所以整体上问题在你来之前就解决了。
如果您的类型具有未免费桥接到 NSCoding 类型的 Codable 属性(如 String 到 NSString),您可以使用 NSCoder 子类方法 encodeEncodable(_:forKey:)
和 decodeDecodable(_:forKey:)
对它们进行编码。
【讨论】:
有关使您的 NSObject 类符合 NSSecureCoding 的示例,请参阅github.com/mattneub/Programming-ios-Book-Examples/blob/…。 所以它是 NSCoding(或 NSSecureCoding),而不是 Codable。当我向 NSCoding 添加基本一致性时,它会显示“在隐式生成的 super.init 调用中未初始化属性‘self.filterStyle’”……可能是因为我有一个接受“filterStyle”的初始化程序。所以我应该使用它的原始值手动编码/解码枚举? 当然,那会很好用;我自己做那种事情。 另外请注意,如果您的枚举是 Codable,您可以使用 NSCoder 子类方法encodeEncodable(_:forKey:)
和 decodeDecodable(_:forKey:)
将其纳入 NSCoding 情况。我会将其添加到我的答案中。以上是关于Swift Codable:标记对象以进行状态恢复的主要内容,如果未能解决你的问题,请参考以下文章
在 Swift 中实例化一个新的 Codable 对象的最简单方法是啥?