Swift Codable:标记对象以使用状态恢复
Swift Codable: marking an object to work with state restoration
我有一个 Swift class,它存储当前应用于我的视图控制器的不同类型的过滤器。我想使用状态恢复来保存它,这样如果用户离开应用程序然后回来,即使应用程序被系统终止,过滤器也会恢复。
我不确定最好的方法是什么。我相信这与 Codable
有关,但如何使它与 UIViewController encoding/decoding.
一起工作
首先,class:
@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:]: unrecognized selector sent to instance 0x6000014cb640
所以我将 Codable
作为协议添加到 CJDataViewControllerFilters
class,并添加了基本一致性:
@objcMembers class CJDataViewControllerFilters: NSObject, Codable {
func encode(to encoder: Encoder) throws {
print("CJDataViewControllerFilters: encode")
}
required init(from decoder: Decoder) throws{
print("init(from decoder)")
}
}
它仍然因为同样的原因崩溃。
我该如何最好地解决这个问题?有没有不同的方法来实现?另外,我如何手动 encode/decode 诸如 NSPreciate 和 NSManagedObjects 数组之类的东西?
Codable
上的大多数示例都参考了 JSON coding/encoding,我在这里不需要(我认为),因此非常感谢您的回答。
NSObject的编码和解码方式是使其符合NSCoding(现在称为NSSecureCoding)。现在您可以使用键控归档器在节省时间时将其放入编码器,并使用键控解档器在恢复时将其从编码器中取出。
大多数built-in类型如NSPredicate已经符合NSSecureCoding,所以问题在你到达之前就已经解决了。
如果您的类型具有未 toll-free 桥接到 NSCoding 类型(如 String 到 NSString)的 Codable 属性,您可以使用 NSCoder 子类方法 encodeEncodable(_:forKey:)
和 decodeDecodable(_:forKey:)
对它们进行编码.
我有一个 Swift class,它存储当前应用于我的视图控制器的不同类型的过滤器。我想使用状态恢复来保存它,这样如果用户离开应用程序然后回来,即使应用程序被系统终止,过滤器也会恢复。
我不确定最好的方法是什么。我相信这与 Codable
有关,但如何使它与 UIViewController encoding/decoding.
首先,class:
@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:]: unrecognized selector sent to instance 0x6000014cb640
所以我将 Codable
作为协议添加到 CJDataViewControllerFilters
class,并添加了基本一致性:
@objcMembers class CJDataViewControllerFilters: NSObject, Codable {
func encode(to encoder: Encoder) throws {
print("CJDataViewControllerFilters: encode")
}
required init(from decoder: Decoder) throws{
print("init(from decoder)")
}
}
它仍然因为同样的原因崩溃。
我该如何最好地解决这个问题?有没有不同的方法来实现?另外,我如何手动 encode/decode 诸如 NSPreciate 和 NSManagedObjects 数组之类的东西?
Codable
上的大多数示例都参考了 JSON coding/encoding,我在这里不需要(我认为),因此非常感谢您的回答。
NSObject的编码和解码方式是使其符合NSCoding(现在称为NSSecureCoding)。现在您可以使用键控归档器在节省时间时将其放入编码器,并使用键控解档器在恢复时将其从编码器中取出。
大多数built-in类型如NSPredicate已经符合NSSecureCoding,所以问题在你到达之前就已经解决了。
如果您的类型具有未 toll-free 桥接到 NSCoding 类型(如 String 到 NSString)的 Codable 属性,您可以使用 NSCoder 子类方法 encodeEncodable(_:forKey:)
和 decodeDecodable(_:forKey:)
对它们进行编码.