【问题标题】:Swift passing method params Struct DecodableSwift 传递方法参数 Struct Decodable
【发布时间】:2017-12-07 13:35:52
【问题描述】:

,Swift 4 如何在方法参数中传递Decodable Struct 并在JSONDecoder() 中解析它? 错误:

不能使用类型为 '(Decodable, 来自:数据)'

struct JsonRespons: Codable {
    let uid: String
    let msisdn: String
    let APK: String
    let fname: String
    let lname: String
}

struct JsonResponsError: Decodable {
    let uid: String
    let error: String
}

extension UIView {

func phoneAuth(serverApi path:String, jsonStruct:Codable){
    let jsonUrlString = Globals.JOSN_API_URL + path
    guard let url = URL(string: jsonUrlString) else {
        return

    }

    URLSession.shared.dataTask(with: url) { (data, response, err) in
        guard err == nil else {
            return
        }

        guard let data = data else { return }

        do {
            let result = try JSONDecoder().decode(jsonStruct.self, from: data)
            self.handleJsonResult(resalt: result as AnyObject)

        } catch let jsonErr {
            print("Error serializing json:", jsonErr)
        }

    }.resume()
}


    func handleJsonResult(resalt:AnyObject){
        print(resalt)
    }

}

【问题讨论】:

  • 目前还不清楚您要在这里实现什么。看起来您希望能够传入 arbitrary Decodable 类型的实例,然后根据原始实例的动态类型将一些数据解码为新实例。但你到底为什么想要那个?之后你打算如何使用result
  • @Hamish 编辑了示例代码我将结果作为方法中的参数传递
  • let result = try JSONDecoder().decode(JsonRespons.self, from: data)替换let result = try JSONDecoder().decode(jsonStruct.self, from: data)让我知道它有效
  • @PrashantTukadiya 是的,它有效,我想将 Struct 作为参数传递,例如 phoneAuth("https://MY_API", JsonRespons.self)
  • @VakhtangiBeridze 你应该在你的问题中说清楚;)在这种情况下你不需要Codable 参数,你需要一个通用占位符T : Decodable 并有一个参数@987654331 @.

标签: json swift decodable


【解决方案1】:

Codable 添加到Landmark 的继承列表会触发满足Encodable and Decodable 中所有协议要求的自动一致性:

您可以使用Codable

struct Landmark: Codable {
    var name: String
    var foundingYear: Int

    // Landmark now supports the Codable methods init(from:) and encode(to:), 
    // even though they aren't written as part of its declaration.
}

替代方案是

func phoneAuth(serverApi path: String, Completion block: @escaping ((Data) -> ())) {

    URLSession.shared.dataTask(with: URL(string: url)!) { (data, res, err) in

        if let d = data {
            block(d)
        }
    }.resume()
}

调用方法

phoneAuth(serverApi: "yourUrl") { (data) in

    do {
        let result = try JSONDecoder().decode(YourDecodable.self, from: data)
    } catch let jsonErr {
        print("Error serializing json:", jsonErr)
    }
}

【讨论】:

  • 我在let result = try JSONDecoder().decode(jsonStruct.self, from: data) 上遇到编译错误无法使用类型为“(可编码,来自:数据)”的参数列表调用“解码”
  • 参考这个stackoverflow.com/a/27162499/6822622,你把协议作为参数传递,没有@Objc是不可能的,
  • 您的解决方案对我有用,虽然有点复杂,但很有帮助,谢谢
【解决方案2】:

你不必将它作为参数传递,你可以像下面这样实现解码

extension UIView {

func phoneAuth(serverApi path:String){
    let jsonUrlString = Globals.JOSN_API_URL + path
    guard let url = URL(string: jsonUrlString) else {
        return

}

URLSession.shared.dataTask(with: url) { (data, response, err) in
    guard err == nil else {
        return
    }

    guard let data = data else { return }

    do {
        let result = try JSONDecoder().decode(JsonRespons.self, from: data)
        self.handleJsonResult(resalt: result as AnyObject)

    } catch let jsonErr {
        print("Error serializing json:", jsonErr)
    }

}.resume()
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-10
    • 1970-01-01
    • 2012-07-14
    相关资源
    最近更新 更多