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

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

Related

I have and array inside the value of dictionary

I have an dictionary and the value containts the array of string as follows
arr = ["key":"["a","b","c","d","e","f","g"]"]
I want the new array to be like
let array = ["a","b","c","d","e","f","g"]
How to parse it
You can access dictionary items in few different ways, the easiest is:
let array = arr["key"]
You may need to conditionally unwrap it
if let array = arr["key"] as? [String] {
// rest of code with array
}

How to pass a Dictionary to Objective-C method in Swift

I need to pass a Dictionary to a Objective-C method in Swift. In Swift the code is like this:
let modelData: Dictionary<String, [Double]> = getModelData()
result = myChilitags.estimate3D(configAt: configFilePath, forModel: modelData);
(The configure file has nothing to do with this problem, just ignore it.)
I used a .h file:
#interface myChilitags : NSObject
+ (nonnull UIImage *)estimate3D:configAt:(NSString *)configFilePath forModel:(nonnull NSDictionary*) modelData;
#end
The question is that I need to do something with the modelData in the Objective-C method estimate3D but I don't know what to do after I passed the Dictionary value modelData to the method.
I tried to just print the modelData value but all that came out was:
1
I also tried to print the value in the Dictionary like:
std::cout << modelData["face001"] << std::endl;
I am pretty sure that there is a key "face001" in the dictionary but the result was still:
1
I know it must have something to do with NSDictionary and Dictionary but I just don't know what to do.
First of all, a Dictionary in Swift is struct, an NSDictionary is class.
Objective-C is not type-safe so it doesn't show an error.
If you try to do the same in Swift, it will tell you
Cannot assign value of type '[String : [Double]]' to type 'NSDictionary'
let swiftDictionary = [String: [Double]]()
var nsDictionary = NSDictionary()
nsDictionary = swiftDictionary //shows error
So you have to convert the Swift dictionary to an NSDictionary.
let modelData: Dictionary<String, [Double]> = getModelData()
let nsModelData = NSDictionary(dictionary: modelData)
result = myChilitags.estimate3D(configAt: configFilePath, forModel: nsModelData);

iOS Swift Updating Dictionary In An Array

I have an array of dictionaries inside a dictionary. I initialize it like this:
var fillups:[NSMutableDictionary] = []
Then I load it like this:
fillups = userDefaults.object(forKey: car) as! NSArray as! [NSMutableDictionary]
Then when I try to update a dictionary element in the array I get the "mutating method sent to immutable object" error. Here's my code to update the record:
let dict=fillups[row]
dict.setValue(odometerField.text, forKey: "odometer")
dict.setValue(gallonsField.text, forKey: "gallons")
fillups[row]=dict
The error occurs in my first setValue line.
Objects that you retrieve from NSUserDefaults are immutable even if they were mutable when they were inserted. You need to take the immutable objects you get from defaults and create mutable versions of them. You also shouldn't force unwrap everywhere if you don't want your app to crash.
if let array = userDefaults.object(forKey: car) as? [NSDictionary] {
fillups = array.map { ($0.mutableCopy() as! NSMutableDictionary) }
}
You also don't need the fillips[row] = dict line since NSMutableDictionary is a reference type and editing the reference you pull out of the array is already editing the one inside the array.
If you want to mutate your dict, you need to declare it with 'var' not with 'let'; 'let' is for constants. Also fix the unwrapping problems pointed out by the comment
let dict=fillups[row]
should be
var dict=fillups[row]

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.

AnyObject to Array?

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

Resources