【问题标题】:Swift: The Mysterious Case of the Vanishing Array ContentsSwift:消失数组内容的神秘案例
【发布时间】:2020-04-13 20:07:13
【问题描述】:

我有以下 Swift 代码,用于将从 JSON 解码的嵌套字典数组的内容提取到可用于 SwiftUI 列表视图(即 Identifiable)的字典数组中。不管怎样,这就是我这样做的原因,问题要简单得多,但很奇怪

struct Salespeople : Codable {
    let salespeople: [Salesperson]?
}

struct Territory: Codable, Identifiable {
    let id: NSInteger
    let name: String
}

struct Salesperson : Codable, Identifiable {
    let id: NSInteger
    let name: String
    let territories: [[String:Territory]]?
    var territoriesArray: [Territory]?
}

let salespeople = try! decoder.decode([[String:Salesperson]].self, from: dataResponse!)

var salespeopleArray:[Salesperson] = []

for salespersonDictionary in salespeople {
    var salesperson = salespersonDictionary["salesperson"]!
    salespeopleArray.append(salesperson)
    salesperson.territoriesArray = [Territory]()

    for territoryDictionary in salesperson.territories! {
        let territory = territoryDictionary["territory"]!
        salesperson.territoriesArray?.append(territory)
    } // <<<< Breakpoint here
}

dump(salespeopleArray)

代码循环遍历一组销售人员,对于每个销售人员,都有一个嵌套循环可从他们可能管理的区域数组中提取并构建派生的区域数组 - 每个销售人员通常只有一个区域,因此代码嵌套循环只执行一次,但代码需要满足更多的可能性。

如果我在处理区域的每个循环结束时设置断点,我可以检查并看到区域已按预期附加到 salesperson.territoriesArray,这表明区域数组已正确初始化并附加到。都很好。

Printing description of salesperson:
▿ Salesperson
  ▿ territories : Optional<Array<Dictionary<String, Territory>>>
    ▿ some : 1 element
      ▿ 0 : 1 element
        ▿ 0 : 2 elements
          - key : "territory"
          ▿ value : Territory
            - id : 801
            - name : "Yorkshire"
  ▿ territoriesArray : Optional<Array<Territory>>
    ▿ some : 1 element
      ▿ 0 : Territory
        - id : 801
        - name : "Yorkshire"

但是,如果我在下一次迭代(即下一个销售人员)上使用调试器检查 salespeopleArray,我已经可以看到上一次迭代(即先前处理的销售人员)的 salesperson.territoriesArray 值已设置为 nil - 为之前的销售人员构建的数组消失了!

这一直持续到两个循环都完成,当我转储“完成”的 salespersonArray 时,不出所料(考虑到正在发生的事情),每个销售人员的 regionsArray 都是 nil。

从转储中提取(salespeopleArray)

 ▿ myapp.Salesperson
    ▿ territories: Optional([["territory": myapp.Territory(id: 1572, name: "Suffolk")]])
      ▿ some: 1 element
        ▿ 1 key/value pair
          ▿ (2 elements)
            - key: "territory"
            ▿ value: myapp.Territory
              - id: 1572
              - name: "Suffolk"
    - territoriesArray: nil

为什么我的领土条目消失了?

感谢阅读。

【问题讨论】:

  • 因为数组是值类型?
  • 销售员的声明是什么?
  • 你不能用在salesperson.territories上的map/compactMap来替换salesperson.territoriesArray吗?
  • @bg2b 感谢您的回复。我已将这些添加到问题中(在第一个代码提取中)。
  • @JoakimDanielson 感谢您的回复。我最初尝试过,但我无法解决领土结构是嵌套字典数组的问题,这些字典具有来自原始 JSON 的根“领土:”——这是我试图用地图解决的问题——因此手动方法。不过我是 Swift 的新手,所以也许有办法解决这个问题。

标签: swift


【解决方案1】:

这并不神秘,它是一个功能。

Swift 数组和字典是值类型。这意味着行

var salesperson = salespersonDictionary["salesperson"]!

制作Salesperson 实例的副本,并将其分配给变量salesperson。您将要进行的更改会更改 salesperson 的内容,但不会更改 salespeople 中键 salesperson 的值。

一种解决方案是将修改后的Salesperson 实例分配回数组salespeople

var salespeople = try! decoder.decode([[String:Salesperson]].self, from: dataResponse!)

var salespeopleArray:[Salesperson] = []

for (index, salespersonDictionary) in salespeople.enumerated() {
    var salesperson = salespersonDictionary["salesperson"]!
    salespeopleArray.append(salesperson)
    salesperson.territoriesArray = [Territory]()

    for territoryDictionary in salesperson.territories! {
        let territory = territoryDictionary["territory"]!
        salesperson.territoriesArray?.append(territory)
    } 
    salespeople[index] = salesperson
}

【讨论】:

  • 对您的 [非常感谢] 固定代码稍作修正,最后一条语句需要是 sa​​lespeopleArray[index] = salesperson 再次感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-08-23
  • 2011-09-27
  • 1970-01-01
  • 2010-10-03
  • 2018-08-18
  • 1970-01-01
  • 2012-12-02
相关资源
最近更新 更多