2016-07-24 84 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和解释我的问题的一切。 –