Could not cast value of type '__NSDictionaryI' to 'NSArray'
The error is pretty clear: json
is a dictionary ([String:Any]
), not an array. Don't use NSArray
– as well as horrible as AnyObject).value(forKey:
– in Swift at all!
And always conditional bind the value to avoid crashes
...
if let json = response.result.value as? [String:Any], // <- Swift Dictionary
let results = json["results"] as? [[String:Any]] { // <- Swift Array
for result in results {
print(result["name"] as! String)
}
There is no key imageURL
in the JSON at all
Could not cast value of type '__NSDictionaryM' to 'NSArray
The error message says
Could not cast the actual type NSDictionary to the expected type NSArray
[NSDictionary]
means an array of dictionaries, but the value of response
is clearly a dictionary, represented by a pair of braces.
So it's actually
let quoteDictionary = quotesData["response"] as! NSDictionary
But it's recommended to use Swift native collection types
let quoteDictionary = quotesData["response"] as! Dictionary<String,AnyObject>
Could not cast value of type '__NSDictionaryI'
.responseJSON
returns deserialized JSON, in this case a Dictionary
. It cannot be cast to Data
what the error clearly confirms.
To get the raw data you have to specify .responseData
Replace
.responseJSON {
response in
switch (response.result) {
case .success:
do {
let users = try JSONDecoder().decode(OrderStore.self, from: response.result.value! as! Data)
with
.responseData {
response in
switch response.result {
case .success(let data):
do {
let users = try JSONDecoder().decode(OrderStore.self, from: data)
Consider that AF 5 supports even .responseDecodable
to decode directly into the model
.responseDecodable {
(response : DataResponse<OrderStore,AFError>) in
switch response.result {
case .success(let users): print(users)
Side notes:
As mentioned in your previous question there is no
AnyObject
in the AF API. The parameters are[String:Any]
andresponseData
is the decoded type. I recommend to make the function generic and use the convenientResult
type.Delete the
break
statements. This is Swift.
Could not cast value of type 'Swift.__SwiftDeferredNSArray' (0x104cd8ae8) to 'NSMutableArray' (0x7fff87c52960)
It seems that JSON.object
may not be an array. Or at least not mutable array. It will be hard for us to identify your issue without having a look into JSON.object
. A quick fix may actually be
let response1 : NSMutableArray = NSMutableArray.init(array: (JSON.object as! NSArray).value(forKey: "media_list") as! NSArray)
but I would try to dig in a bit more. Try to check what exactly is going on and try to avoid old Objective-C Next Step (NS) objects. Do it step by step:
let response1: [Any]? = {
guard let mainArray = JSON.object as? [Any] else {
print("Outer object is not an array. Check type of \(JSON.object)")
return nil
}
var mutableVersionOfArray = mainArray // This already creates a mutable copy because we used "var" instead of "let"
guard let mediaList = mutableVersionOfArray.value(forKey: "media_list") as? [Any] else {
print("Inner object is not an array. Check type of \(mutableVersionOfArray.value(forKey: "media_list"))")
return nil
}
return mediaList
}()
But this code makes no sense to me. Looking at your code I expect that your JSON object looks similar to:
{
"media_list": [{}, {}]
}
in this case you are looking at dictionaries. Try the following:
let mediaList: [Any]? = {
guard let topDictionary = JSON.object as? [String: Any] else {
print("Outer object is not a dictionary. Check type of \(JSON.object)")
return nil
}
guard let mediaListItem = topDictionary["media_list"] else {
print("There is no media_list in payload")
return nil
}
guard let mediaList = mediaListItem as? [Any] else {
print("mediaList is not an array")
return nil
}
return mediaList
}
I hope you can see the difference between an array and a dictionary. Array has some N ordered elements in it while a dictionary has key-value pairs. So to access a value under key you call it as dictionary[key]
. Your whole code if you are correct could simply be:
let response1 = (JSON.object as? [String: Any])?["media_list"] as? [Any]
but if it returns nil it may be a bit hard to debug what went wrong.
Swift JSON error : Could not cast value of type '__NSDictionaryM' to 'NSArray'
The bitnami response starts with a {
and it is therefore a JSON object, which corresponds to an NSDictionary
. The other one starts with [
which indicates an array.
You need to change the type of json
to Dictionary<String, AnyObject>
, and deserialize as follows:
json = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as! Dictionary<String, AnyObject>
Could not cast value of type '__NSArrayI' (0x10df73c08) to 'NSDictionary' (0x10df74108)
Your response is of Array
of Dictionary
not Dictionary
, so if you want all the dictionary you can access it using loop.
if let array = response.result.value as? [[String: Any]] {
//If you want array of task id you can try like
let taskArray = array.flatMap { $0["task_id"] as? String }
print(taskArray)
}
Could not cast value of type '__NSDictionaryI' to 'NSMutableDictionary'
This is no surprise because it's exactly the same behavior as in Objective-C.
In ObjC you cannot cast an immutable type to a mutable. Running this code
NSDictionary *dict = @{@"Foo":@"1"};
NSMutableDictionary *mutableDict = (NSMutableDictionary *)dict;
[mutableDict setObject:@"2" forKey: @"Bar"];
raises an exception
-[__NSSingleEntryDictionaryI setObject:forKey:]: unrecognized selector sent to instance
because the type remains immutable. You have to create a new NSMutableDictionary
instance
NSMutableDictionary *mutableDict = [NSMutableDictionary dictionaryWithDictionary:dict];
Ironically – I'm still talking about ObjC – in case of NSJSONSerialization
the famous option .mutableContainers
comes in. With this option you can create a mutable array / dictionary directly, please note, only in Objective-C.
On the other hand in Swift this option makes no sense anyway because Swift Dictionary
/ Array
and the NSMutable...
counterparts are not related to each other, and in Swift you can make a (native) type mutable simply with the var
keyword.
So write
var json = try JSONSerialization.jsonObject(with: responseData) as! [String:Any]
The bottom line is:
Don't use NSMutable...
collection types in Swift at all.
Related Topics
Ios: Is Core Graphics Implemented on Top of Opengl
Instagram Hooks Pre-Select Media Issue
Posting Photos to Facebook Fan Page with iOS Sdk
How to Fetch All Images from Custom Photo Album - Swift
Present a Modal View Controller with Transparent Background
Passing Variables Between View Controllers
How to Scroll to a Particluar Index in Collection View in Swift
How to Save Created PDF in Document Folder and Merge in iOS
Replace a Particular Color Inside an Image with Another Color
Increment Uislider by 1 in Range 1 to 100
Enable and Debug Zombie Objects in iOS Using Xcode 5.1.1
Swift 3: Replace C Style For-Loop with Float Increment
Uicellview Cell Layout in Swift
How to Clear or Clean Specific Pod from the Local Cocoapods Cache
How to Render View into Image Faster
Add Rounded Corners to All Uiimageviews
How to Programmatically Add a Uisegmentedcontrol to a Container View