`supportsSecureCoding` 在使用 Optimize for Speed 选项时崩溃

`supportsSecureCoding` crashes when using Optimize for Speed option

我在创建使用 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 中的文档说,

This property must return YES on all classes that allow secure coding. Subclasses of classes that adopt NSSecureCoding and override initWithCoder: must also override this method and return YES. // The Secure Coding Guide should be consulted when writing methods that decode data.

Objective-C:

@property (class, readonly) BOOL supportsSecureCoding;

Swift:

public static var supportsSecureCoding: Bool { get }

我正在使用 Xcode 10.0,在 Swift 4.0 和 Swift 4.2 上都试过了。 人们如何解决这个问题?感谢任何帮助。

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

static 在 class 声明中是 final class 的别名,即类型方法 不能在 subclass 中覆盖。你想要的是class方法

public class var supportsSecureCoding: Bool { return true }

可以在子class中用

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

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

这种 hack 会抑制这种过强的优化。

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 }

}

对我有用的修复

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

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

Swift 5.3 编译器现在为未指定安全编码的初始化给出了 NSKeyedArchiver 的弃用消息。但显然该语言不允许在 subclasses 中覆盖它.

当我不覆盖变量时,我得到: 错误:Class 'Subclass' 有一个支持安全编码的 superclass,但是 'Subclass' 覆盖了 -initWithCoder: 而没有覆盖 +supportsSecureCoding。 class 必须实现 +supportsSecureCoding 和 return YES 以验证它的 -initWithCoder: 实现是否符合安全编码。 (NSInvalidUnarchiveOperationException)

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

有条件的解决方法:

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

public class Supertype: NSObject, NSCoding {
     ...

}

子类型:

public class SubType: Supertype, NSSecureCoding {

     public static var supportsSecureCoding = true
     ...
}

这样 var 至少在我使用的所有子类型中都是。

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