问题
I am working on a project that it has a plist contains of rows of dictionaries , and then , I put all the rows of datas to an array and I save it to the useDefaults and all these things seems correct , but in the read method , I understand that my data seems to be coded and it shows it in codes. like this (6b756e74)
I wonder to know how I can decode my data in a very correct way. here is my codes
struct Country : Codable {
let orFlagEmoji, destFlagEmoji : String
private enum CointryKeys : String, CodingKey { case orFlagEmoji, destFlagEmoji }
}
var countries = [Country]()
override func viewDidLoad() {
super.viewDidLoad()
let urlPlist = Bundle.main.url(forResource: "ListinFirstPage", withExtension: "plist")!
let data = try! Data(contentsOf: urlPlist)
do
{
countries = try PropertyListDecoder().decode([Country].self, from: data)
}
catch
{
// Handle error
print(error)
}
savePlaces()
readPlaces()
}
func savePlaces(){
do
{
let placesData = try PropertyListEncoder().encode(countries)
UserDefaults.standard.set(placesData , forKey: "places")
return
}
catch
{
print("SaveError")
}
}
func readPlaces()
{
let loadedcart = UserDefaults.standard.object(forKey: "places")
print(loadedcart as Any)
}
The problem is that when I print loadedcart
(that it should contains countries data) in console it seems data has been coded some how. the output is some numbers not my string data. I really appreciate if some one help me to make it correct. Thank you very much
回答1:
First of all delete readPlaces
. It's pointless
func readPlaces()
{
let loadedcart = UserDefaults.standard.object(forKey: "places")
print(loadedcart as Any)
}
Delete also
private enum CointryKeys : String, CodingKey { case orFlagEmoji, destFlagEmoji }
because the keys are never used (not even correctly spelled CountryKeys
).
Basically your code to load and save the data is correct, it's just misused.
Check if the key places
in UserDefaults
is empty. If so copy the data from the bundle
var countries = [Country]()
override func viewDidLoad() {
super.viewDidLoad()
do {
try loadPlaces()
} catch { print(error) }
}
func loadPlaces() throws
{
let data : Data
if let placesData = UserDefaults.standard.data(forKey: "places") {
data = placesData
} else {
let urlPlist = Bundle.main.url(forResource: "ListinFirstPage", withExtension: "plist")!
data = try Data(contentsOf: urlPlist)
UserDefaults.standard.set(data, forKey: "places")
}
countries = try PropertyListDecoder().decode([Country].self, from: data)
}
func savePlaces()
{
do {
let placesData = try PropertyListEncoder().encode(countries)
UserDefaults.standard.set(placesData , forKey: "places")
} catch {
print("SaveError", error)
}
}
Call savePlaces
always after having modified countries
(except in viewDidLoad)
As mentioned in the comments UserDefaults
is not the right place to save a large set of data. A custom file in the Documents
folder is preferable.
来源:https://stackoverflow.com/questions/58465965/how-to-decode-data-of-an-array-that-is-save-and-read-from-userdeafults-swift