无法使用类型为 '(Codable.Type?

Posted

技术标签:

【中文标题】无法使用类型为 \'(Codable.Type?【英文标题】:Cannot invoke 'decode' with an argument list of type '(Codable.Type?无法使用类型为 '(Codable.Type? 【发布时间】:2019-01-22 14:19:54 【问题描述】:

我正在重构(试图)一位前同事编写的一些网络代码,我想使用新的JSONDecoder

他的网络代码被包装成一个函数getData

func getData(modelToReturn:Proto.Type, configuredRequest:URLRequest) 

正如您从签名中看到的那样,在此方法中您可以指定要返回的模型(即应该对检索到的 JSON 进行反序列化的模型:我不能说得更好,但希望您能理解 :-) )。

在这种情况下,Proto 是任何模型都遵循的协议。

例如。

struct GroceryModel:Proto
  //...

然后以这种方式调用该方法:

net.getData(modelToReturn: GroceryModel.self, configuredRequest: grocery)

调用后,GroceryModel.self 被分配给 net 类 (memberToReturn:Proto.Type?) 的成员,然后 JSON 测试与具有可失败初始化程序的模型结构的一致性:

 if let instance = modelToReturn?.init(json:jsonResult)...

我用以下协议做了一个小测试:

struct Test: Codable 
    let name: String
    let testers: [String]

我用这一行替换了大部分原始代码:

let test = try? JSONDecoder().decode(modelToReturn, from: jsonData)

我的想法是将Codable.self 作为getData 函数的第一个参数传递,但最后一行出现错误:

Cannot invoke 'decode' with an argument list of type '(Codable.Type?, from: Data)'

那么,我怎样才能正确地传递我的模型,以便可以从 decode 函数中使用它?

我必须说,我通过简单地将modelToReturn 替换为Test.self 手动测试了该行,错误消失了。

【问题讨论】:

modelToReturn 不能是 optional。你不能只传递Codable.self,你必须传递传入的类型。如果你只传递Codable,函数将不知道要解码什么。 您的问题似乎与Cannot invoke 'decode' with an argument list of type '(Decodable, from: Data)' 非常相似,答案也应该对您有所帮助。 @DávidPásztor:谢谢,我还没找到 【参考方案1】:

您可以使用下面的泛型。

protocol Proto 


struct Test: Codable, Proto 
    let name: String
    let testers: [String]


func getData<T>(type: T.Type, configuredRequest:URLRequest?) where T : Decodable 
    let data = """

    "name": "a test",
    "testers": ["mike", "bob"],

""".data(using: .utf8)!
    let test = try? JSONDecoder().decode(type, from: data)
    debugPrint(test)


getData(type: Test.self, configuredRequest: nil)

已编辑。

如评论所述,您希望 Type 成为该类的成员,该类具有 getData。 在这种情况下,您可以将泛型应用于类定义,如下所示。

class DataFetcher<T> where T: Decodable 
    func getData(configuredRequest:URLRequest?) 
        let data = """

    "name": "a test",
    "testers": ["mike", "bob"],

""".data(using: .utf8)!
        let test = try? JSONDecoder().decode(T.self, from: data)
        debugPrint(test)
    


DataFetcher<Test>().getData(configuredRequest: nil)

【讨论】:

这并没有解决另一个问题:类成员的类型应该是什么?我试过可解码? (可选)然后,当我必须分配它的值时,XCode 强迫我这样做: T.Type.self as?可解码,但这样错误仍然存​​在,在解码函数中。 “班级成员”是什么意思?例如,在我的代码中,您将哪个类设为 Optional? 正如我所解释的,我将 type 的值分配给我拥有方法 getData 的类的成员,以供以后使用 所以您删除了第一个参数并直接在 DataFetcher 中传递了模型:但是由于委托和关注点分离,我的类 DataFetcher 在 vi​​ewController 中创建了一个实例。是否可以创建 DataFetcher 的实例? 好的,我尝试了实例化,它可以工作。我什至尝试以这种方式将值存储在成员中 var s:T.Type = T.self (可以吗?)它可以工作

以上是关于无法使用类型为 '(Codable.Type?的主要内容,如果未能解决你的问题,请参考以下文章

使用下标时出错:无法使用类型索引为类型值下标...

无法使用类型为“()”的参数列表为类型“Int”调用初始化程序

无法使用类型为“”的参数列表调用类型“”的初始化程序

无法使用类型为“(字符串)”的参数列表调用“执行选择器”

无法使用类型为“(UInt32)”的参数列表调用类型“CGBitmapInfo”的初始化程序

Flutter“此函数的返回类型为void,无法使用”