3

我正在从服务器打开一个标志,以确定要实例化的对象类型。每种类型都是返回类型的子类(Snack在示例中为 )。我的猜测是整个子类与主要问题无关,但为了完整起见,我将其包括在内。

问题是我经常收到 Crashlyticscase "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)
    }
}

具体来说,崩溃发生在“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
    }
}

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

4

1 回答 1

5

发现了问题,男孩是不是很模糊!

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

switch json["SnackName"]

switch json["SnackName"].stringValue

总的来说,这可能是一个好主意,但它之所以必要的原因似乎是 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")
}

然后将这些日志记录语句放入您的 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防止崩溃。

于 2015-03-03T06:07:33.013 回答