Я пытаюсь создать хранилище generic
для своего приложения, где могут храниться Serializable
элементов.Общий параметр T не может быть выведен
У меня есть несколько структур, которые реализуют Serializable protocol
protocol Serializable {
func serialize() -> [String: AnyObject]
init?(byDeserializing dictionary : [String: AnyObject])
}
Это мой Storage Protocol
protocol Storage {
func getItems<T:Serializable>(completion : @escaping ([T]?)-> Void)
func save<T:Serializable>(_ items : [T], completion : @escaping (Bool)-> Void)
}
extension Storage {
func data<T:Serializable>(from serializableItems : [T]) -> Data? {
var serializedItems = [Dictionary<String,AnyObject>]()
for item in serializableItems {
serializedItems.append(item.serialize())
}
guard let serializedData = try? PropertyListSerialization.data(fromPropertyList: serializedItems, format:.binary, options:0) else {
return nil;
}
return serializedData
}
func serializedItems(from data : Data) -> [Dictionary<String, AnyObject>]? {
guard let serilizedItems = try? PropertyListSerialization.propertyList(from: data, options: .mutableContainers, format: nil) as? [Dictionary<String,AnyObject>] else {
return nil
}
return serilizedItems
}
func deserialize<T:Serializable>(from serializedItems: [[String : AnyObject]] ) -> [T] {
var items = [T]()
for serializedItem in serializedItems {
if let item = T(byDeserializing:serializedItem){
items.append(item)
}
}
return items
}
}
Когда приложение хочет восстановить сохраненные он просто позвонить self.storage.getItems
....
func getItems<T : Serializable>(completion: @escaping ([T]?) -> Void) {
let path = fileURL().path
concurrentQueue.async {
guard let serializedItems = NSArray(contentsOfFile: path) as? [[String : AnyObject]], serializedItems.count > 0 else {
completion(nil)
return
}
let deserializedItems = self.deserialize(from: serializedItems)
completion(deserializedItems)
}
}
Я звоню getItems
метод и я получаю эту ошибку компиляции в обеих координаторах хранения
PlistStorageCoordinator
UserDefaultrsStorageCoordinator
Он работал отлично, пока я не добавить дженерик этого метода. Кто-нибудь знает, что может быть неправильным?
Я не знаю, почему, но это исправить. Мне это не нравится, потому что я дублирую код в обоих хранилищах. Кто-нибудь может объяснить это мне?
func getItems<T : Serializable>(completion: @escaping ([T]?) -> Void) {
concurrentQueue.async {
guard let data = self.userDefaults.data(forKey: self.modelKey), let serializedItems = self.serializedItems(from: data), serializedItems.count > 0 else {
completion(nil)
return
}
var items = [T]()
for serializedItem in serializedItems {
if let item = T(byDeserializing:serializedItem){
items.append(item)
}
}
completion(items)
}
}
Как вы определили 'self.storage'. Из-за ошибки я думаю, что это не в формате, где объекты проверяют 'Serializable'. –
Попробуйте добавить информацию о типе элементам, например:' self.storage.getIems {(elements: [CarouselPoi]) в' – Connor
не работает .. 'Невозможно преобразовать значение типа' ([CarouselPoi]) ->() 'до ожидаемого типа аргумента' ([_]?) -> Void' – croigsalvador