Xcode Swift:无法将“__NSCFString”(0x102e8ac50)类型的值转换为“NSDictionary”(0x102e8b8d0)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31797204/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Xcode Swift: Could not cast value of type '__NSCFString' (0x102e8ac50) to 'NSDictionary' (0x102e8b8d0)
提问by wlmrlsda
I am trying to display my JSON information in the debug area but I am having a problem in which I have not found a solution.
我正在尝试在调试区域中显示我的 JSON 信息,但我遇到了一个我没有找到解决方案的问题。
First of all, let me display the code I have so far:
首先,让我显示到目前为止我拥有的代码:
BBUpJSON.swift
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
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
视图控制器.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.
}
}
So, when I run the app with a breakpoint in for jnsextrct in bbupData{
in the BBUpJSON.swiftfile, it shows in the left side of the debug area that I have 20 values. Everytime I run po bbupData
in the right output of the debug area it just partially shows me 3 of the values out of the 20 I have in my JSON file. When I add another breakpoint in completion(jnslst)
located at the end of the same swift file and press Continue program execution, I get the following error: Could not cast value of type '__NSCFString' (0x10c3c2c50) to 'NSDictionary' (0x10c3c38d0)
. It then redirects the error to let image = data["image"] as! NSDictionary
that is located in my JSONExtrct.swift.
因此,当我for jnsextrct in bbupData{
在BBUpJSON.swift文件中使用断点运行应用程序时,它会在调试区域的左侧显示我有20 个值。每次我po bbupData
在调试区域的正确输出中运行时,它只是部分地向我显示 JSON 文件中 20 个值中的 3 个。当我添加另一个断点completion(jnslst)
位于同一迅速文件,然后按结束继续执行程序,我得到以下错误:Could not cast value of type '__NSCFString' (0x10c3c2c50) to 'NSDictionary' (0x10c3c38d0)
。然后它将错误重定向到let image = data["image"] as! NSDictionary
位于我的JSONExtrct.swift 中的错误。
This is the linkto the json file that is trying to extract the information.
这是试图提取信息的 json 文件的链接。
-----UPDATE------
- - -更新 - - -
Modified the values of the strings in JSONExtrct.swiftto:
将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
}
And added the same breakpoints to see the results in BBUpJSON.swift. From the breakpoint for jnsextrct in bbupData{
, it still displays me the same 3 values out of the 20 I have (don't know if that should show that way) when I type po bbupData
in the output area. When I Continue program executionto completion(jnslst)
, it doesn't show me the previous error but it shows me the following output result when typing po jnslst
:
并添加了相同的断点以查看BBUpJSON.swift 中的结果。从断点开始for jnsextrct in bbupData{
,当我po bbupData
在输出区域中输入时,它仍然显示我拥有的 20 个值中的 3 个相同的值(不知道是否应该这样显示)。当我继续程序执行到 时completion(jnslst)
,它不会向我显示以前的错误,但在键入时会向我显示以下输出结果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]
When I continue and add one more breakpoint at the last bracket, it shows me the following error: fatal error: unexpectedly found nil while unwrapping an Optional value
and it redirects the error to completion(jnslst)
showing Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP,subcode=0x0)
当我继续并在最后一个括号处再添加一个断点时,它向我显示以下错误:fatal error: unexpectedly found nil while unwrapping an Optional value
并将错误重定向到completion(jnslst)
显示Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP,subcode=0x0)
UPDATE 2
更新 2
It seems that it reads just one value through jnsextrct
and returns it to jnslst
. Then when I add the other breakpoint in the next screenshot it goes to the next value. When I type po jnslst
in the second screenshot, it returns one [BonBonUp.JSONExtrct]
instead of 20 of them like in the previous update.
似乎它只读取一个值jnsextrct
并将其返回到jnslst
. 然后,当我在下一个屏幕截图中添加另一个断点时,它会转到下一个值。当我输入po jnslst
第二个屏幕截图时,它返回一个[BonBonUp.JSONExtrct]
而不是像上一次更新那样的 20 个。
UPDATE 3
更新 3
Already added CollectionView
to the Main.StoryBoard
but I am getting the following errors when I try to upload JSON information (Not images yet) to each grid. Under JnsGridController.swift, in order to receive the information from my JSON
files, I had to create a new method that would callback as didLoadJns
. Here is the part of that code:
已添加CollectionView
到,Main.StoryBoard
但当我尝试将 JSON 信息(尚未上传图像)上传到每个网格时出现以下错误。在JnsGridController.swift 下,为了从我的JSON
文件中接收信息,我必须创建一个新方法来回调为didLoadJns
. 这是该代码的一部分:
jns = [JsonExtrct]()
let json = JnsJson()
json.loadJns(didLoadJns)
}
func didLoadJns(jns: [JsonExtrct]){
self.jns = jns
collectionView.reloadData()
In json.loadJns(didLoadJns)
, didLoadJns
use to be nil
before I added the func
method but I am getting the following error: Cannot invoke 'loadJns' with an argument list of type '(([JsonExtrct]) -> ())'
在json.loadJns(didLoadJns)
,在添加方法之前didLoadJns
使用,但出现以下错误:nil
func
Cannot invoke 'loadJns' with an argument list of type '(([JsonExtrct]) -> ())'
Also in JnsJson.swift, since I added that callback function in JnsGridControllerits going to be receiving arrays from JsonExtrct
instead of AnyObject
so I changed the function method from func loadJns(completion: ((AnyObject) -> Void)!) {
to func loadJns(completion: ((JsonExtrct) -> Void)!) {
and now I am getting a similar error as the one in JnsGridController: Cannot invoke 'dispatch_async' with an argument list of type '(dispatch_queue_t!, () -> _)'
同样在JnsJson.swift 中,因为我在JnsGridController 中添加了回调函数,它将从而不是接收数组JsonExtrct
,AnyObject
所以我将函数方法从 更改func loadJns(completion: ((AnyObject) -> Void)!) {
为func loadJns(completion: ((JsonExtrct) -> Void)!) {
,现在我收到与JnsGridController类似的错误:Cannot invoke 'dispatch_async' with an argument list of type '(dispatch_queue_t!, () -> _)'
回答by LuckyStarr
The error is clear, you are trying to convert a string to a dictionary. In the json which you posted the key "image", "image2" and "image3" are strings.
错误很明显,您正在尝试将字符串转换为字典。在您发布密钥“image”的 json 中,“image2”和“image3”是字符串。
{
"titulo": "Verox's 1002",
"image": "http://wlodsgn.x10host.com/img/jeans/vrxjns1002/veroxjeans1002_front.jpg",
"image2": "http://wlodsgn.x10host.com/img/jeans/vrxjns1002/veroxjeans1002_rightside.jpg",
"image3": "http://wlodsgn.x10host.com/img/jeans/vrxjns1002/veroxjeans1002_front_b.jpg",
"marca": "Verox",
"color": "Azul",
"tipo": "Jean",
"ref": 1002
}
so the correct way the get those values is:
所以获取这些值的正确方法是:
if let let imageURL = data["image"] as? String {
self.imageUrl = imageURL
}
Avoid to use the explicit unwrap if you are not sure of the type of the object that you are try to casting.
如果您不确定要转换的对象的类型,请避免使用显式解包。
UPDATE
更新
The new error is of the same nature of the previous one, you are implicitly unwrapping a nil value that in this case is the closure completion
. Your definition of the closure is completion: ((AnyObject) -> Void)!
say to the compiler:
新错误与前一个错误具有相同的性质,您隐式地解开一个 nil 值,在这种情况下是闭包completion
。您对闭包的定义是completion: ((AnyObject) -> Void)!
对编译器说的:
Don't worry when you will need to use this closure it will certainly has a non-nil value.
不要担心当你需要使用这个闭包时,它肯定会有一个非 nil 值。
But instead you are passing a nil
value here:
但是,您在nil
这里传递了一个值:
json.loadBbup(nil)
json.loadBbup(nil)
The implicit unwrapping is useful but you are using it in a wrong way. If you want that the completion closure can be nil
you have to define it as optional in this way:
隐式解包很有用,但您以错误的方式使用它。如果您希望完成闭包可以是nil
您必须以这种方式将其定义为可选:
completion: ((AnyObject) -> Void)?
completion: ((AnyObject) -> Void)?
and the call it in this way:
并以这种方式调用它:
completion?(jnslst)
completion?(jnslst)
Regarding the fact that the array contains only 3 values instead 20 there be a lot of reasons. I suggest to put a breakpoint in this line jnslst.append(jnsextrct)
and watch the value of jnsextrct
.
关于数组仅包含 3 个值而不是 20 个值的事实,有很多原因。我建议在这一行放置一个断点jnslst.append(jnsextrct)
并观察jnsextrct
.
As general advices:
作为一般建议:
- avoid to use the implicit unwrapping unless you're certain the variable as non-nil value.
- use let instead var when you don't need to modify a variable; in this way you are certain that value never changes.
- 避免使用隐式解包,除非您确定该变量为非 nil 值。
- 当您不需要修改变量时,请使用 let 代替 var;通过这种方式,您可以确定价值永远不会改变。