ios - NSKeyedArchiver、NSKeyedUnarchiver 和 TimeInterval 四舍五入超过 7 位小数

标签 ios swift nskeyedarchiver nskeyedunarchiver

我在使用 NSKeyedArchiver、NSKeyedUnarchiver 时遇到了问题。

我需要归档字典 ["updated": time, "isFavorite": true],其中 time 是自 1970 年以来的时间间隔。

我的代码是这样的:

import Foundation

extension Data {
    /** Decode data and returns Dictionary<String,Any>, use NSKeyedUnarchiver decoder */
    var decode: [String:Any]?  {
        return NSKeyedUnarchiver.unarchiveObject(with: self) as? [String:Any]
    }
}

extension Dictionary where Key: ExpressibleByStringLiteral, Value: Any {
    /** Encode  Dictionary<String,Any> to the data, use NSKeyedUnarchiver encoder */
    var encode: Data? {
        return NSKeyedArchiver.archivedData(withRootObject: self)
    }
}

/** The current time since 1970 */
var time: Double {
    return Date().timeIntervalSince1970   // example 1491800604.362141
}

//////TEST
let payload: Dictionary<String,Any> = ["updated": time, "isFavorite": true]

print("Data before archiving: \(payload)")

let encodePayload = payload.encode
let decodePayload = encodePayload?.decode

print("Data after unarchive: \(decodePayload!)")

如果时间变量包含 <= 6 位小数,则一切正常,但我得到 >= 7 位小数并且是四舍五入

正确举例

  • 归档前的数据:["updated": 1522537700.689399, “是最爱”:真]
  • 取消存档后的数据:[“更新”: 1522537700.689399, "isFavorite": 1]

例子不正确

  • 归档前的数据:["updated": 1522536585.2104979, “是最爱”:真]
  • 取消存档后的数据:[“更新”: 1522536585.210498, "isFavorite": 1]

最佳答案

正如@rmaddy 所指出的,这是 Double 类型的精度限制:

let payload: Dictionary<String,Any> = ["updated": 1522536585.2104979 as Double, "isFavorite": true]

print("Data before archiving: \(payload)")

let encodePayload = payload.encode
let decodePayload = encodePayload?.decode

print("Data after unarchive: \(decodePayload!)")

输出:

Data before archiving: ["updated": 1522536585.2104979, "isFavorite": true]
Data after unarchive: ["updated": 1522536585.210498, "isFavorite": 1]

但是,您可以使用 NSDecimalNumber 更精确地归档内容:

let decimalNumber = NSDecimalNumber(mantissa: 15225365852104979, exponent: -7, isNegative: false)

let payload: Dictionary<String,Any> = ["updated": decimalNumber, "isFavorite": true]

print("Data before archiving: \(payload.description)")

let encodePayload = payload.encode
let decodePayload = encodePayload?.decode

print("Data after unarchive: \(decodePayload!.description)")

输出:

Data before archiving: ["updated": 1522536585.2104979, "isFavorite": true]
Data after unarchive: ["updated": 1522536585.2104979, "isFavorite": 1]

您也可以使用 Swift 原生的 Decimal 而不是 NSDecimalNumber,但是由于某种原因,它的初始化程序的文档非常少,使用起来也很尴尬:

// If you ever end up compiling for a big-endian architecture,
// the byte ordering here may need to be reversed.
// Of course it's not possible to test whether that's actually true at present.
let decimal = Decimal(_exponent: -7, _length: 56, _isNegative: 0, _isCompact: 0, _reserved: 0, _mantissa: (0xa913, 0xbb30, 0x1763, 0x0036, 0, 0, 0, 0))

let payload: Dictionary<String,Any> = ["updated": decimal, "isFavorite": true]

print("Data before archiving: \(payload.description)")

let encodePayload = payload.encode
let decodePayload = encodePayload?.decode

print("Data after unarchive: \(decodePayload!.description)")

输出:

Data before archiving: ["updated": 1522536585.2104979, "isFavorite": true]
Data after unarchive: ["updated": 1522536585.2104979, "isFavorite": 1]

关于ios - NSKeyedArchiver、NSKeyedUnarchiver 和 TimeInterval 四舍五入超过 7 位小数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49593354/

相关文章:

iphone - 使用 NSCoder 初始化静态单例对象

ios - UICollectionView - 滚动出界

ios - 核心图形旋转矩形

xcode - Swift 代码完成不起作用

ios - 代码=134110 - 强制目标属性上缺少属性值的验证错误

objective-c - 保存自定义对象的 NSArray

iphone - 查找方向改变后元素的位置

android - 如何使用 Dart 签署 Binance HTTP 请求

swift - 如何解包 UInt32?在 swift ?

cocoa - NSImage 的动画在使用 NSKeyedArchiver 存档后丢失