Я хочу сохранить массив пользовательских объектов в 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) ***")
}
}