字符串比较期间SwiftyJSON崩溃:swift_unknownRetain

clo*_*ach 3 crash crashlytics swift swifty-json

我正在从服务器切换标志,以确定要实例化的对象类型.每个类型都是返回类型的子类(Snack在示例中).我的猜测是整个子类事物与主要问题无关,但我将其包含在内以保证完整性.

麻烦的是,我一直在接受Crashlytics报道的坠机事故case "chips":.为了简化我的初始化程序中的解析,我将服务器响应包装在SwiftyJSON中JSON.这一切都在测试中运行良好.

class func fromJSON(json: JSON) -> Snack {
    switch json["SnackName"] {
    case "chips":   // CRASH OCCURS HERE
        return BagOChips(json: json)
    case "apple":
        return Apple(json: json)
    default:
        return Spam(json: json)
    }
}
Run Code Online (Sandbox Code Playgroud)

具体来说,崩溃发生在"SwiftyJSON.swift:1013"(标记如下).Crashlytics将其描述为"0x0000000093a4贝塞的EXC_BAD_ACCESS KERN_INVALID_ADDRESS"和"swift_unknownRetain + 32".

public func ==(lhs: JSON, rhs: JSON) -> Bool {

    switch (lhs.type, rhs.type) {
    case (.Number, .Number):
        return (lhs.object as NSNumber) == (rhs.object as NSNumber)
    case (.String, .String):
        return (lhs.object as String) == (rhs.object as String) // CRASH REALLY OCCURS HERE
    case (.Bool, .Bool):
        return (lhs.object as Bool) == (rhs.object as Bool)
    case (.Array, .Array):
        return (lhs.object as NSArray) == (rhs.object as NSArray)
    case (.Dictionary, .Dictionary):
        return (lhs.object as NSDictionary) == (rhs.object as NSDictionary)
    case (.Null, .Null):
        return true
    default:
        return false
    }
}
Run Code Online (Sandbox Code Playgroud)

知道为什么会失败以及我可以在下一个版本中做些什么来纠正它?

clo*_*ach 5

发现了问题,而男孩却晦涩难懂!

TL; DR - ==完全通过替换来避免SwiftyJSON的功能

switch json["SnackName"]
Run Code Online (Sandbox Code Playgroud)

同

switch json["SnackName"].stringValue
Run Code Online (Sandbox Code Playgroud)

总的来说这可能是一个好主意,但它的必要性似乎是Swift + Foundation如何处理字符串的一个漏洞.我在这里提交了一个开放雷达.

重现此问题所需的只是Xcode 6.1,SwiftyJSON以及我提交给Apple的以下示例代码:

let d = NSDictionary(dictionary: ["foo": "bar"])
let j = JSON(d)

switch (j["foo"]) {
case "bar":
   println("> No crash!")
default:
   println("> default")
}
Run Code Online (Sandbox Code Playgroud)

然后在您的SwiftyJSON副本中输入这些日志记录语句.

public func ==(lhs: JSON, rhs: JSON) -> Bool {
  // Next 2 lines added just for SwiftyCrasher test project.
  println( "> Left: \(_stdlib_getTypeName(lhs.object))" )
  println( "> Right: \(_stdlib_getTypeName(rhs.object))" )

  switch (lhs.type, rhs.type) {
  case (.Number, .Number):
      return (lhs.object as NSNumber) == (rhs.object as NSNumber)
  case (.String, .String):
  ...
}
Run Code Online (Sandbox Code Playgroud)

这显示了崩溃前的以下控制台输出:

> Left: _TtCSs19_NSContiguousString
> Right: _TtCSs19_NSContiguousString
Run Code Online (Sandbox Code Playgroud)

同样,在调试模式下,这不会崩溃.在NSString中装箱"foo"和"bar",或j["foo"]改为j["foo"].stringValue防止崩溃.