Swift 无法推断泛型参数T
我正在尝试为我的应用程序创建一个Swift 无法推断泛型参数T,swift,generics,swift3,Swift,Generics,Swift3,我正在尝试为我的应用程序创建一个通用存储,其中可以存储可序列化的项目 我有一些实现可序列化协议的结构 protocol Serializable { func serialize() -> [String: AnyObject] init?(byDeserializing dictionary : [String: AnyObject]) } 这是我的存储协议 protocol Storage { func getItems<T:Serializable&
通用
存储,其中可以存储可序列化的
项目
我有一些实现可序列化协议的结构
protocol Serializable {
func serialize() -> [String: AnyObject]
init?(byDeserializing dictionary : [String: AnyObject])
}
这是我的存储协议
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
}
}
我调用getItems
方法,在两个存储协调器中都会出现此编译错误
PlistStorageCoordinator
在我向这个方法添加泛型之前,它一直工作得很好。有人知道会出什么问题吗
我不知道为什么,但这可以解决它。我不喜欢它,因为我在两个存储中复制代码。有人能给我解释一下吗?
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)
}
}
func getItems(完成:@escaping([T]?)->Void){
concurrentQueue.async{
guard let data=self.userDefaults.data(forKey:self.modelKey),let serializedItems=self.serializedItems(from:data),serializedItems.count>0 else{
完成(无)
返回
}
变量项=[T]()
对于serializedItems中的serializedItem{
如果let item=T(按反序列化:serializedItem){
items.append(项目)
}
}
完成(项目)
}
}
此协议与您认为的协议不同:
protocol Serializable {
func serialize() -> Dictionary<String, AnyObject>
static func deserialize<T>(_ dictionary : Dictionary<String,AnyObject>) -> T
}
这样,您的系统中的更多部分将如您所期望的那样工作
(综上所述,一定要看看NSCoding
,它已经以一种更强大的方式完成了您想要做的事情。有理由不使用NSCoding
,但要确保它是一种积极的选择,而不仅仅是重新设计。)
本协议也没有说明您的意思:
protocol Storage {
func getItems<T:Serializable>(completion : @escaping ([T]?)-> Void )
func save<T:Serializable>(_ items : [T], completion : @escaping (Bool)-> Void )
}
此功能:
func getItems<T:Serializable>(completion : @escaping ([T]?)-> Void )
func getItems(完成:@escaping([T]?)->Void)
接受两个参数。您可能理解的第二个参数。它是
完成
,它是一个接受可选数组并返回Void的函数。但我相信您误解了第一个参数:T
。调用getItems
时,隐式传递类型作为参数之一。每次调用getItems
,都可以传递不同的T
(就像你可以传递一个不同的completion
。T
没有任何东西能将它与这个存储表联系起来。泛型就是这样工作的。你想要的是一个与存储表联系在一起的类型,并且在存储表中的所有方法中都是一致的。这是一个关联的类型。这个协议没有你想象的作用:
protocol Serializable {
func serialize() -> Dictionary<String, AnyObject>
static func deserialize<T>(_ dictionary : Dictionary<String,AnyObject>) -> T
}
这样,您的系统中的更多部分将如您所期望的那样工作
(综上所述,一定要看看NSCoding
,它已经以一种更强大的方式完成了您想要做的事情。有理由不使用NSCoding
,但要确保它是一种积极的选择,而不仅仅是重新设计。)
本协议也没有说明您的意思:
protocol Storage {
func getItems<T:Serializable>(completion : @escaping ([T]?)-> Void )
func save<T:Serializable>(_ items : [T], completion : @escaping (Bool)-> Void )
}
此功能:
func getItems<T:Serializable>(completion : @escaping ([T]?)-> Void )
func getItems(完成:@escaping([T]?)->Void)
接受两个参数。第二个参数您可能理解。它是
completion
,它是一个接受可选数组并返回Void的函数。但是我相信您误解了第一个参数:T
。当您调用getItems
时,您隐式传递了一个类型作为参数之一。每次调用getItems
,您可以传递不同的T
(就像你可以传递一个不同的completion
。T
没有任何东西可以将它与这个存储绑定在一起。泛型就是这样工作的。你想要的是一个绑定到存储的类型,并且在存储中的所有方法中都是一致的。这是一个关联的类型。你是如何定义self.storage
。)我认为它的格式不符合可序列化
协议。请尝试将类型信息添加到元素中,例如:self.storage.getIems{(elements:[CarouselPoi]),在中它不起作用。无法将类型的值转换为所需的参数类型([CarouselPoi])->(?)->Void
您是如何定义self.storage
的。从错误中,我认为它的格式不符合Serializable
协议。请尝试将类型信息添加到元素中,如:self.storage.getIems{(元素:[CarouselPoi])在
中,它不起作用。无法将类型为
([CarouselPoi])->()`的值转换为预期的参数类型([?]?)->Void
我尝试过你的方法,但我遇到了同样的问题..我编辑了我的问题您在反序列化和getItems中遇到了同样的问题。您一直在注入一个T参数,但没有给编译器任何约束的方式。您希望在获取错误的行中不会出现什么?在StorageCoordinators I sti中我想要T元素,它是在我调用StorageCoordinators的类中,我需要真正的对象。很抱歉,我对泛型理解不太好。我尝试在guard let中添加as
,在getItems调用后在那里获取项,但它不起作用。我尝试过你的方法,但我也遇到同样的问题。我编辑过my Question您在反序列化和getItems中也有同样的问题。您一直在注入一个T参数,但没有给编译器任何约束的方式。您希望在获取错误的行中不会出现什么?在StorageCoordinators中,我仍然需要T元素,它位于我调用StorageCoordinators的类中,我在其中调用了StorageCoordinators需要真正的对象。很抱歉,我不太了解泛型。我已经尝试在guard let中添加作为,在getItems调用后在哪里获取项目,但它不起作用
protocol Storage {
associatedType Element
func getItems(completion : @escaping ([Element]?)-> Void )
func save(_ items : [Element], completion : @escaping (Bool)-> Void )
}
func getItems<T:Serializable>(completion : @escaping ([T]?)-> Void )