No idea why this won't work. The value of this dictionary is a key, yet whenever I try to cast to an array, I get a multitude of errors. Here's what I've tried, with the error I get following each example (in all examples, parameters is type [String : Any]:
let paramsArray = parameters["inputVO"] as AnyObject
if let array = paramsArray as? Array {
}
Error: Generic parameter 'Element' could not be inferred in cast to 'Array<_>'
if let array = parameters["inputVO"] as? Array {
}
Error: Ambiguous reference to member 'subscript'
I'm not sure what else to do to cast the result to an array? I'm sure I've done this before, I have no idea why this is failing. Any help is greatly appreciated.
Edit: Here's the output when I print out params. As expected, it is populated with an Array of Dictionary's.
Optional([["stmtDate": cmd, "transId": identifier, "isSupplementDataAvailable": true]])
Either it's an array
if let array = parameters["inputVO"] as? [[String:Any]] { ... }
or a dictionary
if let dictionary = parameters["inputVO"] as? [String:Any] { ... }
Both types are generics and need specific type information
[[String:Any]] is the short form of Array<Dictionary<String,Any>>
[String:Any] is the short form of Dictionary<String,Any>
Related
I've found an exact solution for above error here http://stackoverflow.com/q/39429342/5309431 and I try to execute that in my code. But the issue is not solved. I don't know what I've made wrong. Please Help
for dict in self.levelRefArr{
if let datas = dict["data"] as? [[String:Any]] { //Type 'NSFastEnumerationIterator.Element' (aka 'Any') has no subscript members
print(datas)
}
}
levelrpfarr is most likely Any, you need to cast it to the actual type which tells the compiler the type of the items in the array
for dict in self.levelRefArr as! [[String:Any]] { ...
I was writing a code for CoreData. My datamodel includes name and moneyAmount. Here's the part of the code I have troubles with
do {
let request = NSFetchRequest(entityName: "MoneyData")
let results = try context.executeFetchRequest(request)
if results.count > 0 {
for item in results as! [NSManagedObject] {
let name = String(item.valueForKey("name"))
let moneyAmount = item.valueForKey("moneyAmount")
moneyManager.addMoney(name, moneyAmount: moneyAmount)
}
}
} catch {
print("There was an error saving data")
}
Now the problem is that my moneyManager.addMoney requires String and Double. However, with this code, the error that I get is:
Optional Chain has no effect, already produces 'Anyobject?'
Cannot convert value of type AnyObject? to expected argument type 'Double'
I don't really understand what it means by Anyobject. I think I should convert anyobject to double to make it work right?
Thanks in advance
valueForKey() returns an object of type AnyObject because there's no way of knowing at compile-time what type of object it's referencing. You can cast to a specific type using as. For example, moneyAmount as? Double will result in an object of type Double?, either containing the numeric value, or being nil if the object wasn't of type Double.
This is what I am trying to do with the dictionary:
if let deliveries = dictionary["deliveries"] as? NSDictionary {
var castedDeliveries = [Double: Double]()
for delivery in deliveries {
if let value = delivery.value as? Double {
castedDeliveries[Double(delivery.key as! NSNumber)] = value //Could not cast value of type 'NSTaggedPointerString' (0x1a1e3af20) to 'NSNumber' (0x1a1e458b0).
}
}
settings!.deliveries = castedDeliveries
}
And this is what I try to cast, as a part of JSON response from server:
deliveries = {
2 = 0;
5 = "2.59";
7 = "3.59";
};
It doesnt work, because there is an error at commented line:
Could not cast value of type 'NSTaggedPointerString' (0x1a1e3af20) to 'NSNumber' (0x1a1e458b0).
You are trying to cast dictionary directly but instead you need to cast each key - value pair. If you want generic solution to this problem take a look at SwiftyJSON library which address JSON parsing problem for you.
Casting doens't mean data transformation from a type to another.
Your dictionary seems to be composed by Integer keys and String values.
If you want to transform in something else you ca use the map function.
let converted = deliveries.map{[Double($0) : Double($1)]}
But pay attention.
Here we are saying, iterate over the dictionary (in the $0 there is the dictionary key in the $1 there is the value) and create a new dictionary that has as a key a Double initialized at the key value and as a new value a Double initialized as the old dictionary value. The last conversion can fail, so the returned data is an optional.
As I noted in the comments, this isn't casting. You want a data conversion. You need to do that explicitly, especially in this case since it might fail.
Looking at the error, I think you really have a dictionary of [String:String] here (in NSDictionary form). That suggests the JSON is badly encoded, but such is life. Assuming that dictionary looks something like this:
let dictionary: NSDictionary = ["deliveries": ["2":"0", "5": "2.59", "7": "3.59"]]
You would convert it to [Double:Double] like this:
if let jsonDeliveries = dictionary["deliveries"] as? [String:String] {
var deliveries: [Double: Double] = [:]
for (key, value) in jsonDeliveries {
if let keyDouble = Double(key),
valueDouble = Double(value) {
deliveries[keyDouble] = valueDouble
}
}
// Use deliveries
}
This silently ignores any values that can't be converted to Double. If you would rather generate errors, use a guard let rather than an if let.
I have a json.I am trying to parse that with that code.But its says
Could not cast value of type '__NSArrayM' to 'NSDictionary'
do {
let dataDictionary: NSDictionary = try NSJSONSerialization.JSONObjectWithData(responseObject as! NSData, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary // <------ Error
if let customerArray = dataDictionary.valueForKey("cart") as? NSArray {
for js in customerArray {
let nameArray = js.valueForKey("name")
let idArray = js.valueForKey("id")
}
}
}
Thank you for your helps
The root object in your data is an array, not a object (dictionary).
You need to dynamically decide how to handle your JSON depending on the deserialized object.
What it's telling you is that the JSON object that you're parsing is not a dictionary, it's an array. So if you change it so that you treat its value as an array instead of a dictionary, you'll be able to iterate over that.
You need to reevaluate your JSON to ensure that it's structured the way you think it is. It would also be useful if you posted the JSON that you're trying to parse so that we can see it's structure as well.
I'm using NSJSONSerialization as so:
let twData: AnyObject? = NSJSONSerialization.JSONObjectWithData(responseData, options: NSJSONReadingOptions.MutableLeaves, error: &dataError)
This gives me an AnyObject?.
From here, I want to convert it to Array<Dictionary<String,String>>
I've tried all sorts, leading up to this:
var twDataArray: Array<Dictionary<String,String>>? = twData? as? Array<Dictionary<String,String>>
which simply gives the error:
Type 'Array>' does not conform to protocol
'AnyObject'.
And putting the simpler version:
var twDataArray = twData as Array
gives the error:
Cannot convert the expression's type 'AnyObject?' to type 'Array'
To cast your data to an array:
var twDataArray = (twData as! NSArray) as Array
The code above first casts twData to an NSArray, and then to an Array via a bridging cast. A bridging cast is a special type of cast which converts an Objective-C type to it's _ObjectiveCBridgeable conformant, Swift counterpart.
(Note that I didn't need to write Array<AnyObject> because the element AnyObject is inferred in the bridging cast from NSArray → Array)
Note that the cast above is a forced downcast. Only use this if you're absolutely sure that twData is going to be an instance of NSArray. Otherwise, use an optional cast.
var twDataArray = (twData as? NSArray) as Array?
Try the following, you can iterate through the array as given below.
for element in twData as! Array<AnyObject> {
print(element)
}
This works in a playground:
var data: Array<Dictionary<String,String>>? = twData as? Array<Dictionary<String, String>>
the difference from your code is that twData does not require the ? at the end - it is an optional so the as? operator will take care of verifying that it can be case to an array of dictionaries - needless to say, if it's nil, as? will evaluate to nil
let twData: Any = NSJSONSerialization.JSONObjectWithData(responseData, options: NSJSONReadingOptions.MutableLeaves, error: &dataError)
Do not use AnyObject. Use Any instead of AnyObject. It will work fine. AnyObject is for all reference type and Array is a value type. That's why this comes. Change it to Any.
As you already know it is a String type you are inserting to something transformable, please do:
if let twoDataArray = twData as? Array<Dictionary<String, String>>{
for data in twoDataArray{
print(data)
}
}
This will guard you from a crashing app when the dictionary is not of type <String,String>.