Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/143.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 无法推断泛型参数T_Swift_Generics_Swift3 - Fatal编程技术网

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 )