Storing Int64 in UserDefaults

2019-02-12 08:43发布

问题:

I define my dictionary like this:

var teamsData = Dictionary<String,Dictionary<String,Int64>>()

Then, I am trying to store it in userdefaults:

NSUserDefaults.standardUserDefaults().setObject(teamsData, forKey: "teamsData")

but it throws the error:

Type Dictionary<String,Dictionary<String,Int64>> does not conform to protocol 'Any Object'

回答1:

A user default object can only be an instance (or a combination of instances) of NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary.

Some Swift types are automatically bridged to Foundation types, e.g. Int, UInt, Float, Double and Bool are bridged to NSNumber. So this could be saved in the user defaults:

var teamsData = Dictionary<String,Dictionary<String,Int>>()

On 64-bit architectures, Int is a 64-bit integer, but on 32-bit architectures, Int is a 32-bit integer.

The fixed-sized integer types such as Int64 are not automatically bridged to NSNumber. This was also observed in Swift - Cast Int64 to AnyObject for NSMutableArray. Therefore, to store 64-bit integers in the user defaults you have to use NSNumber explicitly:

var teamsData = Dictionary<String,Dictionary<String,NSNumber>>()

// Example how to add a 64-bit value:
let value : UInt64 = 123
teamsData["foo"] = ["bar" : NSNumber(unsignedLongLong: value)]


回答2:

Martin's answer is no longer correct for Swift 3 since the set function is now type Any? instead of AnyObject?.

You can store an Int64 in UserDefaults like so:

import Foundation
let value: Int64 = 1000000000000000
UserDefaults.standard.set(value, forKey: "key")
if let value2 = UserDefaults.standard.object(forKey: "key") as? Int64 {
    // value2 is an Int64 with a value of 1000000000000000
    print(value2)
}

You can paste the above code into a Swift playground and try yourself.



回答3:

Swift 4:

You can save int64 as string in UserDefaults

let value: Int64 = 1000000000000000
let stringValue = String(value)
UserDefaults.standard.set(stringValue, forKey: "int64String")

Like that you avoid Int truncation.

And then you can recover the original value:

let int64String = UserDefaults.standard.string(forKey: "int64String")
let originalValue = Int64(int64String!)

This allow you to compare it with other int64 values