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

Crash in SwiftyJSON during string comparison: swift_unknownRetain

我正在从服务器打开一个标志以确定要实例化的对象类型。每种类型都是 return 类型(示例中的 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 at 0x0000000093a4bec8" 和 "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
    }
}

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

找到问题了,小伙子是不是很晦涩!

TL;DR - 通过替换

完全避免 SwiftyJSON 的 == 函数
switch json["SnackName"]

switch json["SnackName"].stringValue

总的来说,这可能是个好主意,但它之所以有必要,似乎是 Swift + Foundation 处理字符串的方式中的一个错误。我已提交公开雷达 here

重现这个问题只需要Xcode6.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

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