【问题标题】:NSKeyedUnarchiver EXC_BAD_INSTRUCTION with protocol带有协议的 NSKeyedUnarchiver EXC_BAD_INSTRUCTION
【发布时间】:2019-11-23 11:34:21
【问题描述】:

我正在更新我的应用程序以支持 IOS 11 版本 目前它适用于 IOS 13.2 但在 IOS 11 和 IOS 12.2 上,我在 NSKeyedUnarchiver decodeObject 有 EXC_BAD_INSTRUCTION

有错误的类

class Seance : NSObject, NSCoding{
  var date: NSDate
  var action: [String:ObjectifData] = Seance.actionStartupPoint()
  var duration = 0.0
  static var instance: Seance? = nil

static func actionStartupPoint() -> [String: ObjectifData]{
    var a: [String: ObjectifData] = [String:ObjectifData]()
    for objectif in Storage.instance.objectif{
        a[objectif.key] = objectif.value.type.initialise
    }
    return a;
}


init(date: NSDate){
    self.date = date;
}

required init(coder decoder: NSCoder){
    self.date = decoder.decodeObject(forKey: "date") as! NSDate
    self.action = try decoder.decodeObject(forKey: "action") as! [String: ObjectifData] // EXC_BAD_INSTRUCTION ERROR
    self.duration = decoder.decodeDouble(forKey: "duration")
}
func encode(with coder: NSCoder){
    print(action)
            print(date)
                    print(duration)
    coder.encode(date, forKey: "date")
    coder.encode(action, forKey: "action")
    coder.encode(duration, forKey: "duration")
}

func convertActionToObjectifData() -> [String: Objectif]{
    var dic: [String: Objectif] = [:]
    for convert in action{
        if Storage.instance.objectif[convert.key] != nil {
            dic[convert.key] = Storage.instance.objectif[convert.key]!
        }
    }
    return dic
}
}

ObjectifData 是具有 3 个父级的协议

这样

class BinaireData : NSObject, NSCoding, ObjectifData {

var validate: Bool = false

func encode(with coder: NSCoder) {
    coder.encode(validate, forKey: "validate")
}
override init(){}
required init(coder decoder: NSCoder) {
    super.init()
    self.validate = decoder.decodeBool(forKey: "validate")
}


func getObjectifType() -> ObjectifType {
    return .binaire
}

func getPrimaryValue() -> Double {
    return validate ? 1 : 0
}

func stringFormatedValue() -> String {
    return validate ? "Oui" : "Non"
}
func updateFromWatch(message: [String : Any]) -> Bool {
    let value: Bool = message["event"] as! Bool
    if(self.validate != value){
        self.validate = value
        return true
    }
    return false
}
}

ObjectifData =

protocol ObjectifData: NSObject {

func getObjectifType() -> ObjectifType
func getPrimaryValue() -> Double
func stringFormatedValue() -> String
func updateFromWatch(message: [String:Any]) -> Bool}

为了加载这个,我在启动时这样做

training = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) as! [String: [Seance]]

Breakpoint Stack trace

经过几项研究,我注意到问题可能是由于 ios11 上的 NSKeyUnarchiver 中不允许的协议而发生的

是真的吗? 我该如何解决这个问题? 谢谢阅读 祝你有美好的一天

【问题讨论】:

  • 更有趣的是ObjectifData是如何定义的。
  • @vadian 感谢回复我已经更新帖子并添加 ObjectifData 声明

标签: swift ios11 ios12 nskeyedunarchiver ios13.2


【解决方案1】:

您正在尝试对类型为 [String: ObjectifData] 的对象进行编码和解码,其中 ObjectifData 是一个协议。你不能那样做;协议不是真正的类型!我对坠机并不感到惊讶。我很惊讶这在 iOS 13 中也没有崩溃。

【讨论】:

  • 另外,你没有收到任何关于不使用 NSSecureCoding 的警告吗?你在强制施放时崩溃了。如果你使用 NSSecureCoding,就不会强制转换。
  • 我也很惊讶,但现在我不知道如何转换我的协议以便可以在 ios 12 或 11 上进行备份
  • 尝试我添加archiver = NSKeyedArchiver.init(requiringSecureCoding: false) 但假或真是一样的
  • 您不能“备份”一个协议。这不是一回事。您需要完全使用其他一些表达方式。您尚未解释此协议的用途。在您的代码中,您只向我们展示了采用此协议的 一个 类型(BinaireData)。这很愚蠢。只被一种类型采用的协议根本就不是协议;它可以(并且应该)在不失一般性的情况下被丢弃。
  • 我使用了 3 种不同类型的 'TimeData' 'BinaireData' 和 'CounterData' 它在字典中非常有用,但也许我必须做 3 种不同的字典才能独立保存。
【解决方案2】:

为了能够对采用ObjectifData 的类进行编码,还必须将其限制为NSCoding

protocol ObjectifData: NSObject, NSCoding

【讨论】:

  • 我已经添加了它,但它不起作用它给我同样的错误
  • 添加异常断点以获取有关崩溃的更多信息。
  • 我没有看到 i.stack.imgur.com/5AMUj.png 可以帮助你吗?
猜你喜欢
  • 2016-04-15
  • 2017-04-24
  • 1970-01-01
  • 2016-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多