简体   繁体   中英

Swift 2.0 initializing nested dictionaries doesn't work as I expected

I am trying to parse some JSON structures into an in-memory map using swift 2.0 - and I keep running across this problem. The first time it happened, I thought it was just some weird thing I did, but it just happened again for the same reason so there is clearly something I don't get.

I have created two unit tests that demonstrate. The first (testFails) assigns a value to a dictionary, then builds up the sub value using a handle to the nested structure. The second (testWorks) always dereferences the full path from the top level dictionary and builds it up. The second version always works, but the first never does. The only things I can think of are either (1), the dictionary is copying the reference to the sub map (subMap), or (2) something funky with optionals is taking place.

Neither makes sense to me, and the debugger in XCode sucks so bad it doesn't ever show values for the structures. The debugger says 0 keys/pairs but when I print the count I get a value, so that is useless. EG, put a breakpoint on the XCTAssertEqual line in testWorks, and the debugger will sometimes say the variable 'map' contains 0 key/value pairs, sometimes just show nothing - even though there clearly is one key/value pair in there.

On a side (newbie) note, I find myself resorting to print statements in this very 'modern' environment because the XCode debugger fails a lot - it shows me no data or something completely foreign. EG, in Java I could check the reference address of the different variables and clear up when proxies/copies were being made, but I can't do that in XCode.

func testFails()
{
    var map = [String: [String: String]]();
    var subMap = [String: String]();
    map["map"] = subMap;
    subMap["1"] = "2";
    XCTAssertEqual(1,  map.count);
    XCTAssertEqual(1,  map["map"]!.count);  // << Fails
    XCTAssertEqual("2", map["map"]!["1"]);  // << Fails
}

func testWorks()
{
    var map = [String: [String: String]]();
    map["map"] = [String: String]();
    map["map"]!["1"] = "2";
    XCTAssertEqual(1,  map["map"]!.count);
    XCTAssertEqual("2", map["map"]!["1"]);
}

Swift Collectiontypes ( Arrays , Dictionaries etc.) are not objects, they are structs.

So when map["map"] = subMap; map will take all info inside subMap and put it under key "map" , note that the reference to subMap is not put under key "map" .

So when you later add a value under key "1" you are not adding it to the value under map["map"] , you are adding it to subMap only.

So then when you try access the "map" value it will contain what subMap contained when being set to "map" in your case empty.

Hopefully I didnt confuse you, terminology isnt my brightest side.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM