2016-10-28 3 views
1

Ich habe ein seltsames Verhalten erlebt, wenn JSON-Daten-Parsing mit Swift 3.Seltsames Verhalten von optionals in Swift 3

do { 
    let json = try JSONSerialization.jsonObject(with: data!, options: []) as! NSDictionary 
    let items:[AnyObject] = (json["items"] as? [AnyObject])! 
    for item in items { 
    let id:String = item["id"] as! String 
    print("ID: \(id)") 
    let info = item["volumeInfo"] as AnyObject 
    print(info) 
    let title = info["title"] 
    print(title) 
    } 
} catch { 
    print("error thrown") 
} 

Dies erzeugt die folgende Ausgabe. Beachten Sie, dass info optional ist, aber wenn ich versuche, es auszupacken, heißt es, dass es nicht optional ist! Das Skript stürzt unter let title = info["title"] ab. Daher kann ich nicht auf den Titelschlüssel zugreifen. Dieses Verhalten hat sich seit Swift 2.

geändert
ID: lbvUD6LUyV8C 
Optional({ 
    publishedDate = 2002; 
    publisher = "Sams Publishing"; 
    title = "Java Deployment with JNLP and WebStart"; 
}) 

Antwort

0

Sie so etwas wie tun aber hoffentlich illustriert dies die Grundidee.

0

Der Laufzeittyp von info ist Optional<Something>, aber die Kompilierung Typ (wie Sie werfen es explizit) ist AnyObject. Wie soll der Compiler wissen, dass die AnyObject eine Optional<Something> sein wird, wenn Sie es nicht sagen (in Form einer Besetzung)?

Versuchen:

let info = item["volumeInfo"] as AnyObject? 

Jetzt ist der Compiler weiß, es ist ein Optional<AnyObject>, so können Sie es auspacken.

do { 
    let json = try JSONSerialization.jsonObject(with: data!) as! [String: Any] 
    let items = json["items"] as! [[String: Any]] 
    for item in items { 
     let id = item["id"] as! String 
     let info = item["volumeInfo"] as! [String: Any] 
     let title = info["title"] as! String 

     print(id) 
     print(info) 
     print(title) 
    } 
} catch { 
    print("error thrown: \(error)") 
} 

Ich könnte darauf hindeuten, den Code des ! Exzision gezwungen Abwickeln (wenn die JSON nicht in Form war man erwartet, wollen diese Sie wirklich abstürzen?):

+0

Versuchte Ihre Lösung, aber jetzt, wenn ich drucken 'info 'Ich bekomme' Optional (Optional ({ publishedDate = "2011-12-28"; Herausgeber = "Jones & Bartlett Publishers"; title = "Programmierung mit Java: Ein Multimedia-Ansatz"; })) ' –

+0

Wenn Sie ein [minimales, vollständiges und überprüfbares Beispiel] (http://stackoverflow.com/help/mcve) veröffentlichen, werde ich mehr als glücklich sein, das Problem mit Ihnen zu lösen. – Alexander

+0

https://gitlab.com/covcom/stack –

0

In Swift 3 muss der Compiler die Typen aller subskribierten Objekte kennen, wenn es sich um ein Array oder ein Dictionary handelt. AnyObject - die in Swift 3 zu Any geändert wurde - ist nicht ausreichend.

Da Sie wissen, dass der Wert für Schlüssel volumeInfo ein Wörterbuch es entsprechend gegossen ist vorzugsweise optionale Bindungen

let info = item["volumeInfo"] as? [String:Any] { 
    print(info) 
    let title = info["title"] as! String 
    print(title) 
} 
0

mit diesem tun sollten:

guard let json = try? JSONSerialization.jsonObject(with: data!, options: []) as! [String: AnyObject], 
    let items = json["items"] as! Array<AnyObject>? else { 
    return 
} 

for item in items { 
    let id = item["id"] as! String 
    if let info = item["volumeInfo"] as? [String: AnyObject] { 
     let title = info["title"] as! String 
    } else { 
     // do something 
    } 
}