Assign value to optional dictionary in Swift

后端 未结 4 1178
北恋
北恋 2020-12-10 04:42

I\'m finding some surprising behavior with optional dictionaries in Swift.

var foo:Dictionary?

if (foo == nil) {
    foo = [\"bar\": \         


        
4条回答
  •  伪装坚强ぢ
    2020-12-10 05:41

    you can use this code

    if var foofoo = foo {
        foofoo["qux"] = "quux"
        foo = foofoo
    } else {
        foo = ["bar": "baz"]    
    }
    

    with this code

    var foo:Dictionary? = Dictionary()
    foo[""]=""
    
    error: 'Dictionary?' does not have a member named 'subscript'
    foo[""]=""
    ^
    

    the error message makes sense to me that Dictionary? does not implement subscript method, so you need to unwrap it before able to use subscript.

    one way to call method on optional is use ! i.e. foo![""], but...

    var foo:Dictionary? = Dictionary()
    foo![""]=""
    
    error: could not find member 'subscript'
    foo![""]=""
    ~~~~~~~~^~~
    

    whereas

    var foo:Dictionary? = Dictionary()
    foo![""]
    

    works


    it is interesting these code failed to compile

    var foo:Dictionary! = Dictionary() // Implicitly unwrapped optional
    foo[""]=""
    
    error: could not find an overload for 'subscript' that accepts the supplied arguments
    foo[""]=""
    ~~~~~~~^~~
    

    var foo:Dictionary! = Dictionary() // Implicitly unwrapped optional
    foo.updateValue("", forKey: "")
    
    immutable value of type 'Dictionary' only has mutating members named 'updateValue'
    foo.updateValue("", forKey: "")
    ^   ~~~~~~~~~~~
    

    the last error message is most interesting, it is saying the Dictionary is immutable, so updateValue(forKey:) (mutating method) can't be called on it

    so what happened is probably that the Optional<> store the Dictionary as immutable object (with let). So even Optional<> it is mutable, you can't modify the underlying Dictionary object directly (without reassign the Optional object)


    and this code works

    class MyDict
    {
        var dict:Dictionary = [:]
    
        subscript(s: String) -> String? {
            get {
                return dict[s]
            }
            set {
                dict[s] = newValue
            }
        }
    }
    
    var foo:MyDict? = MyDict()
    foo!["a"] = "b" // this is how to call subscript of optional object
    

    and this lead me to another question, why Array and Dictionary are value type (struct)? opposite to NSArray and NSDictionary which are reference type (class)

提交回复
热议问题