Could not cast value of type '__NSDictionaryI' to 'NSMutableDictionary'

494 Views Asked by At

I recently started working with swift. I am using below code to cast string to nsmutabledictionary.

print(response);
let responseData = response.data(using: .utf8)!
var json: NSMutableDictionary = try JSONSerialization.jsonObject(with: responseData, options: []) as! NSMutableDictionary;

The response from server for request is like below.

{"token1":"blah.blah.blah","token_type":"smarty","expires_in":1209600,"token2":"blah.blah.blah"}

I am stuck here. Please help.

2

There are 2 best solutions below

0
vadian On BEST ANSWER

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.

0
AnderCover On

jsonObject(with:options:) returns Any, you may try :

let response = """
    {"token1":"blah.blah.blah","token_type":"smarty","expires_in":1209600,"token2":"blah.blah.blah"}
"""
let responseData = response.data(using: .utf8)!
let json = try JSONSerialization.jsonObject(with: responseData, options: []) as! [String: Any]
let mutableDictionary = NSMutableDictionary(dictionary: json)