AnyObject to Array? - ios

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>.

Related

Closure inference in Swift

Why doesn't this compile:
let fullData = [["availabilities": [], "firstSlot": Date()]] as [AnyObject]
let slots = fullData.map { (s) -> [AnyObject] in
return (s as Dictionary)["availabilities"] as [AnyObject]
}
The type of the collection is [AnyObject] so map should be able to infer that "s" is AnyObject. Then there is an explicit cast of the result to [AnyObject] so map should understand that the return is [AnyObject] and the resulting collection [[AnyObject]]
What am I missing?
I don't think this has anything to do with closures or inference. It seems to be a simple matter of types and casting.
You cannot "sideways cast" an AnyObject to a Dictionary (or to anything else for that matter). You have to force-cast it, using as!
Plus, there is no such thing in Swift as a Dictionary plain and simple, because it is a generic. The most general type of dictionary is [AnyHashable:Any].
So the initial cast of s needs to be:
(s as! [AnyHashable:Any])
And by the same token you cannot "sideways cast" the resulting value taken from the dictionary; you must force-cast it:
as! [AnyObject]
Now you can write the whole line as:
return (s as! [AnyHashable:Any])["availabilities"] as! [AnyObject]
Of course, what you're doing here seems completely crazy; you should not be turning anything into an AnyObject. But perhaps this is a toy example drawn from some other context, e.g. you've got JSON coming in? But in that case you should be using Codable to organize the JSON into real objects.

Can't cast from Dictionary value to Array

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>

Core Data and making double from type AnyObject? Swift

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.

Convert from Objective-C NSArray to swift [[String:String]]?

I want to convert from NSArray to swift array [Dictionary<String:String>]
Any help ?
Simple as that:
let someArray = myArray as? [[String:String]]
Optional casting is recommended if you want to make sure you don't get any crashes when converting. You can then use it in if-let constructions like this:
if let dictArray = myArray as? [[String:String]] {
// do something with the array of dictionaries
}
BTW, your initial definition was not correct, there's no such thing as Dictionary<String:String>, the correct definition is Dictionary<String, String>.

Could not cast value of type '__NSArrayM' to 'NSDictionary'

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.

Resources