Xcode Swift: ne peuvent pas chasser valeur de type '__NSCFString' (0x102e8ac50) à "NSDictionary' (0x102e8b8d0)
J'essaie d'afficher mon JSON de l'information dans le débogage de la zone, mais j'ai un problème dont je n'ai pas trouvé une solution.
Tout d'abord, permettez-moi d'afficher le code que j'ai pour l'instant:
BBUpJSON.swift
import Foundation
class BBUpJSON {
func loadBbup(completion: ((AnyObject) -> Void)!) {
var urlString = "http://xxxdsgn.xxxhost.com/json/jnslst.json"
let session = NSURLSession.sharedSession()
let bbupUrl = NSURL(string: urlString)
var task = session.dataTaskWithURL(bbupUrl!){
(data, response, error) -> Void in
if error != nil {
println(error.localizedDescription)
} else {
var error : NSError?
var bbupData = NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers, error: &error) as! NSArray
var jnslst = [JSONExtrct]()
for jnsextrct in bbupData{
let jnsextrct = JSONExtrct(data: jnsextrct as! NSDictionary)
jnslst.append(jnsextrct)
}
let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
dispatch_async(dispatch_get_global_queue(priority, 0)) {
dispatch_async(dispatch_get_main_queue()) {
completion(jnslst)
}
}
}
}
task.resume()
}
}
JSONExtrct.swift
import Foundation
class JSONExtrct {
var titulo : String!
var imageUrl : String!
var imageData : NSData?
var imageUrl2 : String!
var imageData2 : NSData?
var imageUrl3 : String!
var imageData3 : NSData?
var marca : String!
var color : String!
var tipo : String!
var ref : Int!
init(data : NSDictionary) {
self.titulo = getStringFromJSON(data, key: "titulo")
let image = data["image"] as! NSDictionary
self.imageUrl = getStringFromJSON(image, key: "image")
let image2 = data["image2"] as! NSDictionary
self.imageUrl2 = getStringFromJSON(image, key: "image2")
let image3 = data["image3"] as! NSDictionary
self.imageUrl3 = getStringFromJSON(image, key: "image3")
self.marca = getStringFromJSON(data, key: "marca")
self.color = getStringFromJSON(data, key: "color")
self.tipo = getStringFromJSON(data, key: "tipo")
self.ref = data["ref"] as! Int
}
func getStringFromJSON(data: NSDictionary, key: String) ->String{
//let info : AnyObject? = data[key]
if let info = data[key] as? String {
return info
}
return ""
}
}
ViewController.swift
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let json = BBUpJSON()
json.loadBbup(nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
//Dispose of any resources that can be recreated.
}
}
Donc, quand je lance l'application avec un point d'arrêt dans for jnsextrct in bbupData{
dans le BBUpJSON.swift fichier, il affiche dans la partie gauche de la débogage de la zone que j'ai 20 valeurs. Chaque fois que j'exécute po bbupData
dans le droit sortie de débogage de la région c'est que partiellement me montre 3 des valeurs sur les 20 que j'ai dans mon fichier JSON. Quand j'ajoute un autre point d'arrêt dans completion(jnslst)
situé à la fin de la même swift fichier et appuyez sur Continuer l'exécution du programme, j'obtiens l'erreur suivante: Could not cast value of type '__NSCFString' (0x10c3c2c50) to 'NSDictionary' (0x10c3c38d0)
. Il redirige ensuite l'erreur de let image = data["image"] as! NSDictionary
qui se trouve dans mon JSONExtrct.swift.
C'est le lien le fichier json qui est en train d'essayer d'extraire les informations.
-----Mise à JOUR------
Modifié les valeurs des chaînes dans JSONExtrct.swift:
if let imageUrl = data["image"] as? String {
self.imageUrl = imageUrl
}
if let imageUrl2 = data["image2"] as? String {
self.imageUrl2 = imageUrl2
}
if let imageUrl3 = data["image3"] as? String {
self.imageUrl3 = imageUrl3
}
Et a ajouté la même des points d'arrêt pour voir les résultats dans BBUpJSON.swift. Depuis le point d'arrêt for jnsextrct in bbupData{
, il s'affiche toujours moi les 3 mêmes valeurs sur les 20 que j'ai (je ne sais pas si c'était le voir de cette façon) quand je tape po bbupData
dans la zone de sortie. Quand je Continuer l'exécution du programme à completion(jnslst)
, il ne me montre l'erreur précédente, mais il me montre le résultat suivant résultat lors de la saisie de po jnslst
:
(lldb) po jnslst
[BonBonUp.JSONExtrct, BonBonUp.JSONExtrct, BonBonUp.JSONExtrct, BonBonUp.JSONExtrct, BonBonUp.JSONExtrct, BonBonUp.JSONExtrct, BonBonUp.JSONExtrct, BonBonUp.JSONExtrct, BonBonUp.JSONExtrct, BonBonUp.JSONExtrct, BonBonUp.JSONExtrct, BonBonUp.JSONExtrct, BonBonUp.JSONExtrct, BonBonUp.JSONExtrct, BonBonUp.JSONExtrct, BonBonUp.JSONExtrct, BonBonUp.JSONExtrct, BonBonUp.JSONExtrct, BonBonUp.JSONExtrct, BonBonUp.JSONExtrct]
Quand j'ai continuer et d'en ajouter un point d'arrêt à la dernière parenthèse, il m'indique l'erreur suivante: fatal error: unexpectedly found nil while unwrapping an Optional value
et il redirige l'erreur de completion(jnslst)
montrant Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP,subcode=0x0)
Mise à JOUR 2
Il semble qu'il lit qu'une seule valeur par le biais jnsextrct
et le renvoie à jnslst
. Puis, quand j'ai ajouter un autre point d'arrêt dans la capture d'écran suivante, il passe à la valeur suivante. Quand je tape po jnslst
dans la seconde capture d'écran, il renvoie une [BonBonUp.JSONExtrct]
au lieu de 20 d'entre eux, comme dans la précédente mise à jour.
Mise à JOUR 3
Déjà ajouté CollectionView
à la Main.StoryBoard
mais j'obtiens les erreurs suivantes lorsque j'essaie de télécharger JSON de l'information (Pas encore d'images) pour chaque grille. En Vertu De JnsGridController.swift, afin de recevoir les informations de mon JSON
fichiers, j'ai dû créer une nouvelle méthode de callback comme didLoadJns
. Voici la partie de code:
jns = [JsonExtrct]()
let json = JnsJson()
json.loadJns(didLoadJns)
}
func didLoadJns(jns: [JsonExtrct]){
self.jns = jns
collectionView.reloadData()
Dans json.loadJns(didLoadJns)
, didLoadJns
utilisation nil
avant, j'ai ajouté la func
méthode, mais j'obtiens l'erreur suivante: Cannot invoke 'loadJns' with an argument list of type '(([JsonExtrct]) -> ())'
Également dans JnsJson.swift, depuis que j'ai ajouté que la fonction de rappel dans JnsGridController sa va être de la réception des tableaux de JsonExtrct
au lieu de AnyObject
alors j'ai changé la méthode de la fonction de func loadJns(completion: ((AnyObject) -> Void)!) {
à func loadJns(completion: ((JsonExtrct) -> Void)!) {
et maintenant j'obtiens une erreur similaire à celui dans JnsGridController: Cannot invoke 'dispatch_async' with an argument list of type '(dispatch_queue_t!, () -> _)'
OriginalL'auteur wlmrlsda | 2015-08-03
Vous devez vous connecter pour publier un commentaire.
L'erreur est clair, vous tentez de convertir une chaîne de caractères à un dictionnaire. Dans le json qui vous posté la touche "image", "image2" et "image3" sont des chaînes de caractères.
donc la bonne façon de les obtenir ces valeurs est:
Éviter d'utiliser de l'explicite déballer si vous n'êtes pas sûr du type de l'objet que vous essayez de casting.
Mise à JOUR
La nouvelle erreur est de même nature que le précédent, vous êtes implicitement d'ôter une valeur nulle qui dans ce cas est la fermeture
completion
. Votre définition de la fermeture estcompletion: ((AnyObject) -> Void)!
dire au compilateur:Mais au lieu de cela vous êtes de passage à un
nil
valeur ici:json.loadBbup(nil)
L'implicite déballage est utile, mais vous l'utilisez dans un mauvais sens. Si vous voulez que l'achèvement de fermeture peut être
nil
vous avez à le définir comme facultatif de cette façon:completion: ((AnyObject) -> Void)?
et de l'appeler de cette façon:
completion?(jnslst)
Concernant le fait que le tableau ne contient que 3 valeurs au lieu de 20-il y avoir un tas de raisons. Je vous suggère de mettre un point d'arrêt sur cette ligne
jnslst.append(jnsextrct)
et de regarder la valeur dejnsextrct
.Que les conseils généraux:
J'ai mis à jour ma réponse.
Merci encore pour aider! A ajouter un supplément de
?
à la achèvement?
(jnslst) de la ligne à la fin, car il me faisait une erreur, si je n'ai pas l'ajout d'une?
ou!
. Concernant l'ajout d'un point d'arrêt àjnslst.append(jnsextrct)
, je vais poster dans ma question deux captures d'écran des valeurs.Oui, vous devez utiliser un point d'interrogation à l'appel de la fermeture, depuis maintenant, il est facultatif (j'ai mis à jour la la réponse). Pour l'autre problème, essayez de changer le nom de cette variable
jnsextrct
à l'intérieur de la boucle dansjnsextrct2
de sorte qu'il n'entre pas en conflit avec les autres sur le pour-chaque déclaration. Il ne devrait pas être un problème, mais sans avoir le code "sous les yeux" il est difficile de trouver le bug.Auriez-vous l'esprit si je vous ai envoyé le projet de sorte que vous pouvez obtenir un rapide coup d'œil et m'aider à comprendre?
OriginalL'auteur LuckyStarr