如何在使用`if let`可选展开(交换)功能时获取参考

时间:2018-07-05 10:59:59

标签: swift if-statement reference

我正在尝试在[String: Any]内注入一些值以供以后使用。

我的代码的简约示例:

var info = ["Person" : [
  "Age" : 20,
  "Name" : "Ratul Sharker"
]]

print(info)

if var person = info["Person"] as? [String:Any] {
  person["height"] = 5.5
  print("~~> Height injected")

  //
  //  however if i reassign the
  //  person into the info, then 
  //  the info appear into the print
  // info["Person"] = person
}
print(info)

该代码也被共享here

此代码的输出给了我

["Person": ["Age": 20, "Name": "Ratul Sharker"]]
~~> Height injected
["Person": ["Age": 20, "Name": "Ratul Sharker"]]

显然,我正在注入的height无效,因为发生可选的拆包时,它会创建person字典的另一个副本。因此,更改仍然是本地的。将本地人分配到字典中可以达到目的。

在这里,我想要的是不复制值,而使用if let进行可选的拆包。我有什么办法可以告诉if let构造,以便它采用值的引用而不是值。我已经对此场景进行了很多搜索,所有这些都是通过使用&inout引用函数来获得的。

谢谢。

5 个答案:

答案 0 :(得分:2)

您需要将新词典person保存回原来的词典。

if var person = info["Person"] {
    person["height"] = 5.5
    info["Person"] = person // <------ important
}

更新

由于您不想使用可选的绑定语句,因此这是另一种解决方案

struct Person {
    let age: Int
    let name: String
    var height: Float?
}

var person = Person(age: 20, name: "Ratul Sharker", height: nil)

person.height = 5.5

答案 1 :(得分:1)

就像您写的一样,词典值类型。因此,如果要进行更改,则必须在原始var上进行更改(在您的情况下为info)。

这意味着要像下面这样:

info["Person"]?["height"] = 5.5

答案 2 :(得分:0)

您的代码给出了错误error: downcast from '[String : Any]?' to '[String : Any]' only unwraps optionals; did you mean to use '!'? if var person = info["Person"] as? [String:Any] { ~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~ 因为在此info [“ person”]中还返回了一个可选的您,并且您将其再次包装

var info = ["Person" : [
"Age" : 20,
"Name" : "Ratul Sharker"
]]

print(info)

if var person = info["Person"] {
person["height"] = 5.5
info["Person"] = person
print("~~> Height injected")

//
//  however if i reassign the
//  person into the info, then
//  the info appear into the print
// info["Person"] = person
}
print(info)

还有另一个问题,为什么您的字典没有更改,是因为在可选绑定中,当值被取消包装时,它被复制到另一个变量中,而您更改它的副本时,只需将该副本分配给您的变量就可以了!

答案 3 :(得分:0)

更改不会保存在您的信息变量中,因为此行:

if var person = info["Person"] as? [String:Any]

正在创建一个新变量(人),您只需将高度值注入该变量。

要将其保存到您的信息对象中,您可以执行以下操作:

info[“person”] = person

info[“person”][“height”] = 5.5

希望有帮助。

编辑:如果要先检查此人,请执行以下操作:

if var person = info[“person”] as? [String: Any]
{
    person[“height”] = 5.5
    self.info[“person”] = person    //saves the injected person to info
}

答案 4 :(得分:0)

它与数组中的Matrix非常相似

  

请注意,如果您在另一本词典中有一个词典,则必须将每个词典视为一个变量

var parentDictionary : [String:Any] = ["Developer":["iOS":"Swift"]]

print(parentDictionary["Developer"]) 

// log -> ["iOS":"Swift"]

print(parentDictionary["Developer"]["iOS"]) 

// log -> "Swift"

现在就您而言,是否需要检查某人是否具有字典之类的价值

if var person = info["Person"] as? [String:Any] {
  print("\(person.values)")
 // log -> [20, "Ratul Sharker", 5.5]
}

但这不是您想在字典中添加参数的方式