我想将一组自定义对象保存到UserDefaults
。在大多数情况下,它运行良好,但有时执行会冻结在步骤2上,并在几秒钟后继续执行,我将数据对象保存到UserDefaults
。它不是定期发生,但是当数组包含许多元素时,似乎更经常发生此问题。
从未抛出任何错误,似乎编码或保存Data
在某种程度上已损坏,但我不明白这里可能是什么问题。
我的自定义对象类:
struct AWFavourite: Codable {
enum MediaType: String, Codable {
case album
case artist
case playlist
}
let identifier: String
let title: String
let mediaType: MediaType
let image: UIImage?
let source: AWMediaSource
enum CodingKeys: String, CodingKey {
case identifier
case title
case mediaType
case image
case source
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let imageData = try container.decode(Data.self, forKey: .image)
image = NSKeyedUnarchiver.unarchiveObject(with: imageData) as? UIImage
title = try container.decode(String.self, forKey: .title)
identifier = try container.decode(String.self, forKey: .identifier)
mediaType = try container.decode(MediaType.self, forKey: .mediaType)
source = try container.decode(AWMediaSource.self, forKey: .source)
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(title, forKey: .title)
try container.encode(identifier, forKey: .identifier)
try container.encode(mediaType, forKey: .mediaType)
print("Probuje obrazek")
let imageData = NSKeyedArchiver.archivedData(withRootObject: image as Any)
print("zrobilem obrazek")
try container.encode(imageData, forKey: .image)
print("Przeszedlem obrazek")
try container.encode(source, forKey: .source)
}
}
以及保存收藏夹数组的方法
static private let key = "favouritesKey"
var favourites: [AWFavourite]!
private func saveFavourites(_ completion: (() -> Void)?) {
DispatchQueue.global(qos: .background).async {
do {
print("Step 1")
let data = try JSONEncoder().encode(self.favourites)
print("Step 2") // Most often the freezing occurs here and Step 3 gets printed after few seconds
UserDefaults.standard.set(data, forKey: AWFavouriteManager.key)
print("Step 3") // Step 3 gets printed but Step 4 is printed after few seconds, sometimes even more than 20
DispatchQueue.main.async {
print("Step 4\n")
completion?()
}
} catch let error {
print("*** \(error.localizedDescription) ***") // No error is ever thrown here, app just freezes
}
}
}
// This is called in init
func loadFavourites() {
favourites = []
guard let data = UserDefaults.standard.data(forKey: AWFavouriteManager.key) else {
return
}
do {
favourites = try JSONDecoder().decode([AWFavourite].self, from: data)
print(favourites.map({$0.mediaType.rawValue}))
} catch let error {
print("*** \(error.localizedDescription) ***")
}
}