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

时间:2015-03-01 05:01:43

标签: swift crash crashlytics swifty-json

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

麻烦的是,我一直在case "chips":线上的Crashlytics报告崩溃事件。为了简化初始化程序中的解析,我将服务器响应包装在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)
    }
}

具体来说,崩溃发生在" SwiftyJSON.swift:1013" (标在下面)。 Crashlytics将其描述为" EXC_BAD_ACCESS KERN_INVALID_ADDRESS位于0x0000000093a4贝塞和#34;和" 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
    }
}

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

1 个答案:

答案 0 :(得分:5)

发现了问题,而男孩却模糊不清!

TL; DR - 通过替换

完全避免使用SwiftyJSON的==功能
switch json["SnackName"]

switch json["SnackName"].stringValue

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

重现此问题所需要的只是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")
}

然后在您的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):
  ...
}

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

> Left: _TtCSs19_NSContiguousString
> Right: _TtCSs19_NSContiguousString

同样,在调试模式下,此不会崩溃。拳击" foo"和" bar"在NSString中,或将j["foo"]更改为j["foo"].stringValue也可以防止崩溃。