Как получить ссылку при использовании `if let` необязательной распаковки (swift) - PullRequest
0 голосов
/ 05 июля 2018

Я пытаюсь вставить некоторые значения в [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)

Код также доступен здесь

Вывод этого кода дает мне

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

Очевидно, что height, который я вводю, не имеет никакого эффекта, потому что, когда происходит необязательное развертывание, создается еще одна копия словаря person. Таким образом, изменение остается локальным. Назначение местного человека в словарь делает свое дело.

Здесь я хочу не копировать значение при необязательном развертывании, используя if let. Есть ли способ, которым я могу сказать if let конструкцию, чтобы он брал ссылку на значение вместо значения. Я много искал об этом сценарии, все, что я получал, передавая ссылку на функцию, используя & и inout.

Заранее спасибо.

Ответы [ 5 ]

0 голосов
/ 05 июля 2018

это так похоже на матрицу в массивах

обратите внимание, что если у вас был словарь в другом словаре, вы должны рассматривать каждый словарь как переменную

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]
}

но вы не хотите добавлять параметры в свой словарь

0 голосов
/ 05 июля 2018

Изменение не сохраняется в вашей информационной переменной, потому что эта строка:

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
}
0 голосов
/ 05 июля 2018

ваш код дает ошибку error: downcast from '[String : Any]?' to '[String : Any]' only unwraps optionals; did you mean to use '!'? if var person = info["Person"] as? [String:Any] { ~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~ потому что в этой информации ["person"] также возвращает необязательное значение you, и вы снова оборачиваете его

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)

и для другого вопроса, почему ваш словарь не изменяется, потому что в необязательном связывании, когда значение развернуто, оно копируется в другую переменную, а вы меняете копию этого, просто присваивайте эту копию своей переменной, и все готово !!

0 голосов
/ 05 июля 2018

Вам необходимо сохранить новый словарь 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
0 голосов
/ 05 июля 2018

Как вы и написали, словарь - это тип значения . Поэтому, если вы хотите внести изменения, вы должны сделать это в исходной переменной var (в вашем случае это info).

это означает сделать это следующим образом:

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

...