Dictionary 为Swift中的可选字典赋值

Dictionary 为Swift中的可选字典赋值,dictionary,swift,Dictionary,Swift,我在Swift中发现一些可选字典的惊人行为 var foo:Dictionary<String, String>? if (foo == nil) { foo = ["bar": "baz"] } else { // Following line errors with "'Dictionary<String, String>?' does // not have a member named 'subscript'" foo["qux"

我在Swift中发现一些可选字典的惊人行为

var foo:Dictionary<String, String>?

if (foo == nil) {
    foo = ["bar": "baz"]
}
else {
    // Following line errors with "'Dictionary<String, String>?' does
    // not have a member named 'subscript'"
    foo["qux"] = "quux"
}
var-foo:字典?
如果(foo==nil){
foo=[“bar”:“baz”]
}
否则{
//以下带有“'Dictionary'”的行错误是否存在
//没有名为“subscript”的成员
foo[“qux”]=“qux”
}
我已经玩了很多次了,试图找出我可能缺少的东西,但似乎没有什么能让这段代码像预期的那样工作,除非使字典不再是可选的。我错过了什么

我能得到的最接近的是以下内容,但这当然是荒谬的

var foo:Dictionary<String, String>?

if (foo == nil) {
    foo = ["bar": "baz"]
}
else if var foofoo = foo {
    foofoo["qux"] = "quux"
    foo = foofoo
}
var-foo:字典?
如果(foo==nil){
foo=[“bar”:“baz”]
}
如果var foooo=foo,则为else{
foofoo[“qux”]=“qux”
foo=foo
}
您可以使用此代码

if var foofoo = foo {
    foofoo["qux"] = "quux"
    foo = foofoo
} else {
    foo = ["bar": "baz"]    
}
var foo:Dictionary<String, String>? = Dictionary()
foo[""]=""

error: 'Dictionary<String, String>?' does not have a member named 'subscript'
foo[""]=""
^

使用此代码

if var foofoo = foo {
    foofoo["qux"] = "quux"
    foo = foofoo
} else {
    foo = ["bar": "baz"]    
}
var foo:Dictionary<String, String>? = Dictionary()
foo[""]=""

error: 'Dictionary<String, String>?' does not have a member named 'subscript'
foo[""]=""
^
鉴于

var foo:Dictionary<String, String>? = Dictionary()
foo![""]


这就引出了另一个问题,为什么
Array
Dictionary
是值类型(struct)?与
NSArray
NSDictionary
相反,它们都是引用类型(类)

当您意识到可选字典不是字典时,就会产生闪光点。可选的任何东西都不是那个东西!它是可选的!!就这些。Optional本身就是一个类型。可选的只是一个枚举,它包含可能的情况nil和一些值。包装的值是一个完全不同的对象,存储在内部

所以可选的anything与该类型的东西不一样。不是那个东西!这只是一个选项。拿到东西的唯一方法就是把它打开


隐式展开的可选项也是如此;不同之处在于隐式unwrapped选项愿意“自动”生成(公开)包装的值。但事实上,它仍然是包装好的。而且,正如Bryan Chen所观察到的,它是不可改变的;可选的只是为你保留它-它没有给你一个玩它的地方。

这是因为你的字典是可选的。如果为nil,则不会向其添加条目

您可以这样做:

var dict: [String : String]?
if let dict = dict {
  dict["key"] = "value" // add a value to an existing dictionary
} else {
  dict = ["key" : "value"] // create a dictionary with this value in it
}
或者,如果给您一个可选的字典,例如HTTPHeaders(在AlamoFire中是[String:String]字典),并且您想要添加一个非nil的值,或者使用此值创建一个非nil的值,您可以这样做:

let headers: HTTPHeaders? // this is an input parameter in a function for example

var customHeaders: HTTPHeaders = headers ?? [:] // nil coalescing
customHeaders["key"] = "value"

我在Swift 3.1中尝试了这一点,它成功了:

if (myDict?[key] = value) == nil {
    myDict = [key: value]
}

我完全理解这一切?还有!但你的最后一句话是对的。我很惊讶
Array
Dictionary
是结构而不是对象。有趣的是,你不能创建一个真正不可变的数组,只能创建一个固定长度的数组,这是完全不同的。部分原因是它们不需要是类——在Swift中,结构几乎就是一个类,事实上在某些方面类更具限制性(通过引用传递,没有类变量等等),在基础语言中定义的类型都不是类;一切都是一个枚举或一个struct@matt我猜按值传递是一件好事(所以您不会意外地更改某些内容并导致意外行为),但另一方面,数组的实现方式是它是struct,但实际上是按引用传递的(如C)。另外,一个对象应该通过值或引用传递更多的是关于语义的东西(我们希望在不同的上下文下有不同的行为)实验你所说的,我发现
var a:Int?;如果是nil{a++}
也是一个错误。有鉴于此,optionals似乎没有我最初想象的那么有用……这让人沮丧。@GarrettAlbright有用的和有用的一样。你没有遵循这个成语,所以你把自己绊倒了。我不知道你想做什么,但也许这就是你的意思:
var a:Int?;如果var b=a{a=++b}
我觉得我必须分配另一个变量并来回传递该变量的值是愚蠢的。(我的代码示例并不实用;只是一些示例,因为我正在试图发现这里真正发生了什么。)我所期望的是可选变量是可以为零的变量,或者在不为零时可以作为标准变量,但情况似乎并非如此。@GarrettAlbright没错,它们不是。但愚蠢的是,如果不需要的话,将值保存在可选的包装中。一旦你知道它不是零,也不会是零,你应该把它从包装中拿出来,忘记可选的。我的观点是,你的例子是人工的,但是考虑到它的人工性,有一个正确的习惯用法来做这件事。那么你说创建新变量并交换它是正确的习惯用法,是吗?
let headers: HTTPHeaders? // this is an input parameter in a function for example

var customHeaders: HTTPHeaders = headers ?? [:] // nil coalescing
customHeaders["key"] = "value"
if (myDict?[key] = value) == nil {
    myDict = [key: value]
}