Search code examples
swiftnsmutabledictionary

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


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.


Solution

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