【问题标题】:How to pass Encodable or Decodable as parameter in Swift 4?如何在 Swift 4 中将 Encodable 或 Decodable 作为参数传递?
【发布时间】:2018-10-26 06:19:28
【问题描述】:

我正在学习 JSONParsing。我跟着教程,我得到的是:

    guard let url = URL(string: "http://localhost/test-api/public/api/register") else { return }

    var request  = URLRequest(url: url)

    request.httpMethod = "POST"

    let newUser = User.init(name: self.collectionTF[0].text, email: self.collectionTF[1].text, password: self.collectionTF[2].text)

    do {

        let jsonBody = try JSONEncoder().encode(newUser)

        request.httpBody = jsonBody

    } catch { }

    URLSession.shared.dataTask(with: request) { (data, response, error) in

        guard let data = data else { return }

        do {

            let json = try JSONSerialization.jsonObject(with: data) as? [String:Any]

            print(json!)

            DispatchQueue.main.async {

            if json!["status"] as! Int == 200
            {
                GeneralHelper.shared.keepLoggedIn()

                NavigationHelper.shared.moveToHome(fromVC: self)
            }

            }

        } catch { print(error.localizedDescription)}

        }.resume()

好的,这就是我为注册所做的。现在,我想创建一个 Helper,它将对 @escaping 做同样的事情,因为我们都需要解析后的 JSON 作为回报。

所以,我将endPoint 作为字符串传递,然后尝试传递这个新用户,它是Encodable,将来也可以是Decodable,但它会引发错误Cannot invoke 'encode' with an argument list of type '(Codable)'。有人可以帮忙吗?而且,在JSONParsing 中多次调用这个函数,这样会更好吗?

编辑:-所以,我现在使用networkRequestfunction,这就是我所做的。

 let newData = User.init(name: "Rob", email: "abc@gmail.com", password: "12345678")

ApiHelper.sharedInstance.networkRequest_Post(urlString: "register", header: nil, encodingData: newData) { (response: User, urlRes, error) in
        <#code#> }

现在,它给了我这个错误:Cannot convert value of type '(User, _, _) -&gt; ()' to expected argument type '(_?, HTTPURLResponse?, Error?) -&gt; ()'。有什么帮助吗?

【问题讨论】:

标签: ios json swift xcode api


【解决方案1】:

我在我的项目中使用了相同的功能

希望下面的代码会有所帮助

    func networkRequest_Post<T: Decodable, Q: Encodable>(urlString: String,header:[String:String]?,encodingData: Q,completion: @escaping (T?, HTTPURLResponse?, Error?) -> ()) {

    guard let url = URL(string: urlString) else { return }
    let config = URLSessionConfiguration.default
    config.timeoutIntervalForRequest = 300.0
    config.timeoutIntervalForResource = 300.0
    if header != nil{
        config.httpAdditionalHeaders = header
    }
    let session = URLSession(configuration: config)
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    do {
        let jsonBody = try JSONEncoder().encode(encodingData)
        request.httpBody = jsonBody
    } catch {}
    let task = session.dataTask(with: request) { (data,response, err) in

        if let response = response {
            print(response)
        }
        if let err = err {
            print("Failed to fetch data:", err.localizedDescription, "Error Description\(err)")
            return
        }
        guard let data = data else { return }
        do {
            print(String(data: data, encoding: String.Encoding.utf8) as Any)
            let dataReceived = try JSONDecoder().decode(T.self, from: data)
                completion(dataReceived,response as? HTTPURLResponse,err)
        } catch let jsonErr {
            print("Failed to serialize json:", jsonErr, jsonErr.localizedDescription)
            completion( nil,response as? HTTPURLResponse,jsonErr)
        }
    }
    task.resume()
}

使用 -

         let newdata = User(name: "Abhi", email: "jhjhj@jhj.co", password: "123hguhj")
    networkRequest_Post(urlString: "YOUR_URL", header: nil, encodingData: newdata) { (RESPONSE_DATA:User?, URL_RESPONSE, ERROR) in
        // Do your network work here
    }

    struct User : Codable {
      var name: String?
      var email: String?
      var password: String?
    }

【讨论】:

  • 好的,你能给我看一个函数吗,比如用可解码和可编码调用函数,对不起,我不太清楚,当谈到泛型时,我对它很陌生.一个小指南会帮助我。
  • 我需要页眉吗?
  • 我对标题有要求,所以添加了它。我已经选择并更新了我的代码
  • 我已经更新了我的问题,请检查编辑部分,这让我现在很头疼。你知道这里出了什么问题吗?
  • 预期的类型是可选的,您传递的是非可选值,请传递如下值 ApiHelper.sharedInstance.networkRequest_Post(urlString: "register", header: nil, encodingData: newData) { (response : User?, urlRes?, error?) in
【解决方案2】:

您可以通过以下方式使用泛型...

func requestWith<T>(method: HTTPMethod, action: String,  params: Parameters?, for type: T.Type, success: @escaping (AnyObject) -> Void, failure: @escaping (AnyObject) -> Void) where T: Codable {


//do your stuff..your logic goes here..see below example

     guard let serverData = response.data else {
           return
        }

   do {
     let decoder = JSONDecoder()
     let responseData = try decoder.decode(type, from: serverData)
       success(responseData as AnyObject)
    } catch {
      print("Error = \(error.localizedDescription)")
       failure(error.localizedDescription as AnyObject)
   }

}

【讨论】:

  • Codable 是 Decodable & Encodable 协议的超级...试试吧。
  • Unspecified AnyObject 不适合泛型函数。更好func requestWith&lt;T&gt;(method: HTTPMethod, action: String, params: Parameters?, success: @escaping (T) -&gt; Void, failure: @escaping (Error) -&gt; Void) where T: Codable {
  • 我知道,这里你用过JSONDecoder,所以我想问如果我想encode怎么办?
  • @vadian,这只是一个例子:)
  • 是的,但是请为那些一起复制和粘贴代码的人推荐更好的示例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-13
  • 1970-01-01
  • 1970-01-01
  • 2016-02-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多