【问题标题】:How to replace/update dictionary in Array of Dictionary based on Type如何根据类型替换/更新字典数组中的字典
【发布时间】:2020-09-14 14:01:37
【问题描述】:

我收到来自服务器的 JSON 响应,并在屏幕上显示电话号码。

现在用户可以更改/更新任何电话号码,因此我们必须更新同一对象中的特定手机号码并将其发送到服务器。

"phone_numbers": [
                {
                    "type": "MOBILE",
                    "number": "8091212121"
                },
                {
                    "type": "HOME",
                    "number": "4161212943"
                },
                {
                    "type": "BUSINESS",
                    "number": "8091212344"
                }
            ]

我的模型类是这样的:

public struct Contact: Decodable {
    public let phone_numbers: [Phone]?
}

public struct Phone: Decodable {
    public let type: PhoneType?
    public let number: String?
}

我正在努力为特定电话号码更新此 JSON 对象。

例如,如果我只想在上面的数组中更新 BUSINESS 编号,那么最好的方法是什么。 我正在使用 XCode 11 和 Swift 5。

【问题讨论】:

  • 不是输入字符串吗?为什么将其声明为 PhoneType ?你被困在哪里了?请展示您的尝试。
  • 没有。它不是字符串,它是来自服务器的所有预期电话号码类型的枚举。基于Type,我们确定要更新的号码。后端也使用类似的逻辑来识别。
  • 我一直在更新这本词典。如前所述,例如,如果用户输入 BUSINESS 类型的新手机号码,我如何在数组中找到该对象并替换现有号码?
  • 您想在哪里更新号码?在您存储此 json 的数组中?
  • 您的问题缺少很多可以帮助我们回答的细节,所以对您来说显而易见的事情可能对那些试图帮助您的人来说不是。我试图在字里行间阅读并猜测您的问题可能是什么,但我真的不知道我的回答是否解决了您的问题,或者您是否完全陷入了其他问题。为获得最佳结果,不要只说“我在挣扎”,而是向我们展示一些未能完成您认为应该做的事情的代码。

标签: ios arrays swift xcode dictionary


【解决方案1】:

有几种方法可以解决这个问题(我假设 PhoneType 是您在某处拥有的枚举)

您可以遍历数组并仅保护业务编号,就像这样

for phone in phone_numbers{
    guard phone.type == .MOBILE else { continue }
    // Code that modifies phone
}

您可以像这样过滤和迭代数组

phone_numbers.filter {$0.type == .BUSINESS }.forEach { phone in
// Modify phone here
} 

然后你可以用它的索引修改数组中正确的值,像这样

for (phoneIndex, phone) in phone_numbers.enumerated() {
    guard phone.type == .BUSINESS else { continue }
    phone_numbers[phoneIndex].type = ANOTHER_TYPE
}

有些人可能会争辩说,第二个比第一个更受欢迎,因为它是一个更高阶的函数,但在我的日常活动中,我倾向于同时使用这两者,并认为这是一个品味问题

【讨论】:

  • 我已经完成了这部分。我的确切问题是在此之后该怎么办?因为您的代码正在过滤掉要更新的对象。但是现在如何更新phone_numbers 对象?
  • 你可以试试phone.type = ANOTHER_TYPE。如果这不起作用,您需要修改数组本身,因此它将是phone_numbers[PHONE_INDEX].type = ANOTHER_TYPE。我将编辑答案以在数组修改中包含迭代
【解决方案2】:

我正在努力为特定电话号码更新此 JSON 对象。

更新时它不应该是 JSON 对象。将 JSON 视为一种传输数据的格式。传输后,您应该将其解析为可以使用的内容,例如字典数组或其他内容。如果您已经这样做了,那么您可能会问的更具体的问题是:

  • 如何在数组中找到特定条目?
  • 如何修改结构的字段?
  • 如何将数组中的一个条目替换为另一个条目?

查看结构的定义后,我认为您遇到的问题可能与您声明它们的方式有关:

public struct Phone: Decodable {
    public let type: PhoneType?
    public let number: String?
}

因为您使用let 声明了typenumber,所以初始化后这些字段无法更改。如果您希望 Phone 结构的字段可修改,则需要使用 var 而不是 let 声明它们。

Contact 结构也是如此:

public struct Contact: Decodable {
    public let phone_numbers: [Phone]?
}

您已将phone_numbers 声明为不可变 数组,因为您使用let 而不是var。如果您希望能够在phone_numbers 中添加、删除或修改数组,则需要改用var

您现在拥有的结构声明可以很好地从 JSON 读取数据,因为 JSON 数据的所有组件都是使用 JSON 中的值构造的。但同样,如果您希望能够进行更改,则需要通过切换到 var 声明来修改这些结构。

【讨论】:

    【解决方案3】:

    因为您的所有属性都定义为常量 (let),所以无法更新任何内容。您必须使用更新的电话号码初始化并返回一个新的 Contact 对象。

    如果将属性更改为var,则可以更新:

    public enum PhoneType: String, Decodable {
        case mobile = "MOBILE"
        case home = "HOME"
        case business = "BUSINESS"
    }
    
    public struct Contact: Decodable {
        public var phone_numbers: [Phone]?
    
        mutating func update(phoneNumber: String, for type: PhoneType) {
            guard let phone_numbers = self.phone_numbers else { return }
    
            for (i, number) in phone_numbers.enumerated() {
                if number.type ==  type {
                    self.phone_numbers![i].number = phoneNumber
                }
            }
        }
    }
    
    public struct Phone: Decodable {
        public var type: PhoneType?
        public var number: String?
    }
    
    var contact = try! JSONDecoder().decode(Contact.self, from: jsonData)
    contact.update(phoneNumber: "123456", for: .business)
    

    【讨论】:

      猜你喜欢
      • 2015-10-30
      • 1970-01-01
      • 2012-03-01
      • 1970-01-01
      • 2012-07-25
      • 2021-07-13
      • 1970-01-01
      • 1970-01-01
      • 2021-02-19
      相关资源
      最近更新 更多