【问题标题】:Swift Codable: marking an object to work with state restorationSwift Codable:标记对象以进行状态恢复
【发布时间】: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 CJ​​ournal[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 编码/编码,我在这里不需要(我认为),因此希望得到答复。

【问题讨论】:

    标签: ios swift codable state-restoration


    【解决方案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 情况。我会将其添加到我的答案中。
    猜你喜欢
    • 1970-01-01
    • 2010-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-25
    • 1970-01-01
    • 2015-02-06
    • 1970-01-01
    相关资源
    最近更新 更多