2016-07-24 179 views
0

我有一個字典的引用,當我調試代碼時,我可以看到引用正在填充,但實際的字典沒有得到任何值。字典參考不更新字典

var newItems = [String:Dictionary<String,AnyObject>]() 

     for item in self.items{ 
      let itemRef = ref.child("items").childByAutoId() 
      //let itemOptions: NSMutableArray = [] 
      //let itemRemovedOptions: NSMutableArray = [] 
      //let itemDiscounts: NSMutableArray = [] 

      newItems.updateValue([String:AnyObject](), forKey: "\(itemRef.key)") 

      newItems["\(itemRef.key)"]?.updateValue(item.parentCategory.id, forKey: "parentCategoryId") 
      newItems["\(itemRef.key)"]?.updateValue(item.item.id, forKey: "itemId") 
      newItems["\(itemRef.key)"]?.updateValue(item.item.name, forKey: "name") 
      newItems["\(itemRef.key)"]?.updateValue(item.qty, forKey: "qty") 
      newItems["\(itemRef.key)"]?.updateValue(item.discountAmount, forKey: "discountAmount") 
      newItems["\(itemRef.key)"]?.updateValue(item.notes, forKey: "notes") 
      newItems["\(itemRef.key)"]?.updateValue(item.price, forKey: "price") 

      //set options 
      newItems["\(itemRef.key)"]?.updateValue([String:Dictionary<String,AnyObject>](), forKey: "options") 
      for option in item.options{ 
       if var optionsRef = newItems["\(itemRef.key)"]?["options"] as? [String:Dictionary<String,AnyObject>]{ 
        optionsRef.updateValue([String:AnyObject](), forKey: "\(option.item.id)") 
        optionsRef["\(option.item.id)"]?.updateValue(option.item.name, forKey: "name") 
        optionsRef["\(option.item.id)"]?.updateValue(option.group.id, forKey: "group") 
        optionsRef["\(option.item.id)"]?.updateValue(option.qty, forKey: "qty") 
        optionsRef["\(option.item.id)"]?.updateValue(option.price, forKey: "price") 
       } 
      } 
     } 
+0

對於大多數不必要的複雜數據結構中的獎和代碼去... – Alexander

+0

我在代碼中的結構中有代碼,但我需要將它傳遞給只接收字典的firebase,因此所有的轉換。任何解決方案 –

回答

1

這裏的主要問題是,當你說if var optionsRef = newItems["\(itemRef.key)"]?["options"] as? [String:Dictionary<String,AnyObject>],你正在做的詞典的副本,因爲字典是在雨燕值類型。因此,字典的所有後續修改僅適用於您的本地副本,而不是您希望的副本。爲了緩解這種情況,您必須將修改後的字典版本分配到您希望更改的數據結構中。

但除了這個主要問題之外,這個代碼還有很多其他更軟的問題。這個問題有50多個觀點,沒有答案。人們看到這個,說「不要!」並尖叫着跑開。以下是一些要點:

  1. 符合您對速記符號的使用。 [String : [String : AnyObject],而不是[String : Dictionary<String, AnyObject>]
  2. 請勿單獨使用字符串插值("\(foo)")將類型轉換爲字符串。如果這些值已經是字符串,請直接使用它們。如果他們不是,請將其轉換爲String(foo)
  3. 請勿使用updateValue(_:forKey:)。幾乎沒有理由。傾向下標語法。
  4. 初始化複雜結構(如字典)時,首先進行初始化,然後添加它。不要添加它,然後通過繁瑣的複製/粘貼重複訪問它。
    • 對您的情況,請考慮newItems["\(itemRef.key)"]?.updateValue(...。每行都必須對密鑰進行散列處理,並用於從newItems字典中檢索值。然後,必須檢查返回的值爲零(由?.運算符),如果nil不執行任何操作,則執行方法。你知道這個值不會是零,因爲你設置了它,但它必須做所有這些檢查。
  5. 喜歡字典文字儘可能在突變。
  6. 不要使用基礎數據結構(NSArray,NSDictionary等),這是絕對必要的。

這是我對這段代碼的看法。這可能需要一些觸摸起伏,但這個想法是有:

var newItems = [String : [String : AnyObject]() //fixed inconsistent application of shorthand syntax 

let itemRef = ref.child("items").childByAutoId() //this shouldn't be in the loop if it doesn't change between iterations 

for item in self.items { 

    // There's pretty much no reason to ever use updateValue(_:forKey:), when you can just use 
    // subscript syntax. In this case, a Dictionary literal is more appropriate. 

    var optionsDict = [String : [String : AnyObject](); 

    for option in item.options { 
     optionsDict[option.item.id] = [ 
      "name" : option.item.name, 
      "group" : option.group.id, 
      "qty" : option.qty, 
      "price" : option.price, 
     ] 
    } 

    newItems[itemRef.key] = [ 
     "parentCategoryId" : item.parentCategory.id, 
     "itemId" : item.item.id, 
     "name" : item.item.name, 
     "qty" : item.qty, 
     "discountAmount" : item.discountAmount, 
     "notes" : item.notes, 
     "price" : item.price, 
     "options" : optionsDict 
    ] 
} 

下面是避免了單獨定義optionsDict一種替代方案:

let itemRef = ref.child("items").childByAutoId() 

for item in self.items { 

    newItems[itemRef.key] = [ 
     "parentCategoryId" : item.parentCategory.id, 
     "itemId" : item.item.id, 
     "name" : item.item.name, 
     "qty" : item.qty, 
     "discountAmount" : item.discountAmount, 
     "notes" : item.notes, 
     "price" : item.price, 
     "options" : item.options.reduce([String : AnyObject]()) { (var dict, option) in 
      optionsDict[option.item.id] = [ 
       "name" : option.item.name, 
       "group" : option.group.id, 
       "qty" : option.qty, 
       "price" : option.price, 
      ] 
     } 
    ] 
} 
+0

我對此無限感激! Swift中的許多概念讓我目瞪口呆。我知道我們不應該感謝,但你應該得到一個! –

+0

你絕對可以感謝這裏的人,而不是問題的一部分。禮貌受到好評。你對我的回答有任何疑問嗎? – Alexander

+0

目前沒有,但是在你演示的內容中有一些概念。昨晚我確實想出了聲明嵌套字典,然後在聲明實際項目時分配它們。但是,你已經構建了這個方法,清潔和易於維護!簡短符號的混合是因爲我從網絡上拉出答案,所以我沒有發佈這實際上是我使用<>進行的操作。也知道字典是一種價值類型......這將有助於:p和解釋我的問題的一切。 –