使用“优化速度”选项时,{supportsSecureCoding`崩溃

时间:2018-09-27 20:12:41

标签: swift nssecurecoding

我在创建使用NSSecureCoding及其子类的类时遇到了麻烦。

class ClassA: NSObject, NSSecureCoding {
    public static var supportsSecureCoding: Bool { return true }
}

class ClassB: ClassA {
    public static var supportsSecureCoding: Bool { return true } // "Cannot override static var"
}

由于NSObject.h中的文档说,

  

此属性必须在所有允许安全编码的类上返回YES。采用NSSecureCoding并覆盖initWithCoder:的类的子类也必须覆盖此方法并返回YES。       //编写用于解码数据的方法时,应查阅《安全编码指南》。

Objective-C:

@property (class, readonly) BOOL supportsSecureCoding;

迅速:

public static var supportsSecureCoding: Bool { get }

我正在使用Xcode 10.0,在Swift 4.0和Swift 4.2上都尝试过。 人们如何解决这个问题?任何帮助表示赞赏。

更新: 使用public class var supportsSecureCoding时,它可以编译,但是使用“优化速度”时,它将在运行时崩溃。

4 个答案:

答案 0 :(得分:4)

当它的定义与其父类相同时,Swift的当前优化器似乎会抑制生成重写的getter方法。多么聪明的优化器!?

这种黑客行为会抑制这种过强的优化。

class ClassB: ClassA {

    //...

    static private var secureCoding = true
    override public class var supportsSecureCoding: Bool { return secureCoding }

}

static private let的效果不同。因此,当Swift优化器更加聪明时,上面的代码可能无法正常工作。最好尽快发送错误报告。


似乎Swift优化器已经足够聪明了,上面的解决方法可能不起作用。 (请参阅Martin R的评论。)

您可能需要删除private

class ClassB: ClassA {

    //...

    static var secureCoding = true
    override public class var supportsSecureCoding: Bool { return secureCoding }

}

答案 1 :(得分:1)

类声明中的

staticfinal class的别名,即类型方法 不能在子类中覆盖。您想要的是一种class方法

public class var supportsSecureCoding: Bool { return true }

可以在子类中用

覆盖
override public class var supportsSecureCoding: Bool { return true }

答案 2 :(得分:0)

修复了我的问题

private static var secureCodingWorkaround = true
@objc override public class var supportsSecureCoding: Bool { return secureCodingWorkaround }

答案 3 :(得分:0)

我无法获得上述任何答案。这绝对是 Apple 方面的一个错误,他们需要解决,因此请确保将其发送到反馈系统中。我什至没有运气就添加了@objc。

对于未指定安全编码的初始化,Swift 5.3 编译器现在为 NSKeyedArchiver 提供了弃用消息..但显然该语言不允许在子类中覆盖它。

当我不覆盖变量时,我得到: 错误:“子类”类具有支持安全编码的超类,但“子类”覆盖 -initWithCoder: 并且不覆盖 +supportsSecureCoding。该类必须实现 +supportsSecureCoding 并返回 YES 以验证其 -initWithCoder: 的实现是否符合安全编码。 (NSInvalidUnarchiveOperationException)

当我覆盖变量时,我得到:“无法覆盖静态变量”

有条件的解决方法:

这个解决方法对我有用,因为我有一个超类型,它有点抽象,因为它在没有子类型的情况下永远不会被使用。如果您有类似的设置,这应该适合您:

public class Supertype: NSObject, NSCoding {
     ...

}

子类型:

public class SubType: Supertype, NSSecureCoding {

     public static var supportsSecureCoding = true
     ...
}

这样,var 至少出现在我使用的所有子类型中。

如果您直接实例化并使用 Supertype,这对您不起作用。