【问题标题】:Write setter and getter method for variable while mapping swift?快速映射时为变量编写setter和getter方法?
【发布时间】:2018-07-14 21:23:37
【问题描述】:

我想在映射时修改 roomTotal 键的值。请参考以下代码:

struct TransactionInfoModel: Codable {
   var currencyCode: String
   var total: Double
   var roomCurrencyCode: String
   var exchangeRate: Double

   var roomTotal: Double {
      get {
        let y = (self.roomTotal*100).rounded()/100
        return y
      }
   }
}

最初,roomTotal 键的值来自服务器,例如“427.3000000002”,但我想在映射时存储值“427.3”。上面的代码不起作用。

寻找一些解决问题的建议。

【问题讨论】:

  • 使用Decimal,而不是Double
  • @Alexander 我尝试使用 Decimal 但仍然面临同样的问题。
  • 您真的需要更改值吗?或者您只是想确保当您在 UI 中显示它时,您只能看到两位小数?如果您需要实际四舍五入并准确地用两个小数位表示(例如,您正在根据其中许多值进行数学运算),那么您应该使用Decimal。如果您只需要确保只显示两位小数,那么您可以确保在显示结果时使用NumberFormatter,并忽略Double 引入的任何可忽略不计的不精确性,并保持您的Codable 逻辑简单。
  • @Rob 是的,我需要更改值,之前我尝试使用 Decimal,但它不起作用。

标签: json swift mapping


【解决方案1】:

请参阅 this answer 以了解如何对 Double 值进行舍入并返回将保留舍入的 Decimal 值,而不会在尝试以二进制浮点表示形式表示十进制值时产生任何伪影。然后,您可以像这样得到四舍五入的Decimal 值:

let roomTotal = 427.3000000002
let value = roomTotal.roundedDecimal(to: 2)

如果你想用指定的小数位数显示它(以及本地化用户当前语言环境的字符串),你可以使用NumberFormatter

let formatter = NumberFormatter()
formatter.maximumFractionDigits = 2
formatter.minimumFractionDigits = 2

if let string = formatter.string(for: value) {
    print(string)
}

现在,如果您希望 JSONDecoder 为您进行此转换,您可以,但我可能倾向于让 struct 准确表示返回的内容,避免任何复杂的 init(from:) 实现,但可能包括一个计算属性,以您想要的格式返回值,例如:

struct TransactionInfoModel: Codable {
   var currencyCode: String
   var total: Double
   var roomCurrencyCode: String
   var exchangeRate: Double
   var roomTotal: Double

   var roundedRoomTotal: Decimal {
       return roomTotal.roundedDecimal(to: 2)
   }
}

如果您在解码时需要对roomTotal 进行四舍五入,您可以编写init(from:) 来实现:

struct TransactionInfoModel: Codable {
    var currencyCode: String
    var total: Double
    var roomCurrencyCode: String
    var exchangeRate: Double
    var roomTotal: Decimal

    init(from decoder: Decoder) throws {
        let values       = try decoder.container(keyedBy: CodingKeys.self)
        currencyCode     = try values.decode(String.self, forKey: .currencyCode)
        total            = try values.decode(Double.self, forKey: .total)
        roomCurrencyCode = try values.decode(String.self, forKey: .roomCurrencyCode)
        exchangeRate     = try values.decode(Double.self, forKey: .exchangeRate)
        roomTotal        = try values.decode(Double.self, forKey: .roomTotal).roundedDecimal(to: 2)
    }
}

或者,您可以省略init(from:),但在解析后手动舍入:

struct TransactionInfoModel: Codable {
    var currencyCode: String
    var total: Double
    var roomCurrencyCode: String
    var exchangeRate: Double
    var roomTotal: Decimal
}

还有:

var object = try! JSONDecoder().decode(TransactionInfoModel.self, from: data)
var rounded = Decimal()
NSDecimalRound(&rounded, &object.roomTotal, 2, .plain)
object.roomTotal = rounded

【讨论】:

  • 谢谢,@Rob 根据您的代码 roomTotalroundedRoomtotal 将分别保存值 427.3000000002427.30。这很好,但我面临另一个问题,即我必须将所有数据发送到服务器,因为它来自服务器。根据这个需要,roomTotal 键的值应该是427.30。为此,当我尝试将 roundedRoomtotal 键的值分配给 roomTotal 键时,我必须将其转换为双精度,这又会产生同样的问题。
  • 在我的扩展答案中查看一些选项
猜你喜欢
  • 2016-11-30
  • 2011-12-22
  • 2011-04-14
  • 2017-09-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-07
  • 2014-03-27
相关资源
最近更新 更多