2015-03-01 5 views
3

Я включаю флаг с сервера, чтобы определить, какой тип объекта должен быть создан. Каждый тип является подклассом возвращаемого типа (Snack, в примере.) Я предполагаю, что весь предмет подкласса не имеет отношения к основной проблеме, но я включаю его для полноты.Ошибка в SwiftyJSON во время сравнения строк: swift_unknownRetain

Проблема в том, что я довольно последовательно получаю сообщение об аварии с 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) 
    } 
} 

В частности, сбой происходит в "SwiftyJSON.swift: 1013" (обозначены ниже). Crashlytics описывает это как «EXC_BAD_ACCESS KERN_INVALID_ADDRESS на 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 
    } 
} 

Любая идея, почему это не удается и что я мог бы сделать, чтобы исправить ее в нашем следующем выпуске?

ответ

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 также предотвращают сбой.