如何在 Swift 4 中将 Encodable 或 Decodable 作为参数传递?
Posted
技术标签:
【中文标题】如何在 Swift 4 中将 Encodable 或 Decodable 作为参数传递?【英文标题】:How to pass Encodable or Decodable as parameter in Swift 4? 【发布时间】: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, _, _) -> ()' to expected argument type '(_?, HTTPURLResponse?, Error?) -> ()'
。有什么帮助吗?
【问题讨论】:
我已经创建了包装类你应该试试github.com/PrashantKT/AlamofireHelperLayer 【参考方案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 协议的超级...试试吧。 UnspecifiedAnyObject
不适合泛型函数。更好func requestWith<T>(method: HTTPMethod, action: String, params: Parameters?, success: @escaping (T) -> Void, failure: @escaping (Error) -> Void) where T: Codable
我知道,这里你用过JSONDecoder
,所以我想问如果我想encode
怎么办?
@vadian,这只是一个例子:)
是的,但是请为那些一起复制和粘贴代码的人推荐更好的示例。以上是关于如何在 Swift 4 中将 Encodable 或 Decodable 作为参数传递?的主要内容,如果未能解决你的问题,请参考以下文章
使用 Swift 的 Encodable 将可选属性编码为 null 而无需自定义编码
协议类型“Encodable”的值不能符合“Encodable”;只有结构/枚举/类类型可以符合协议
如何在 Xcode 中将 Swift 版本从 5 更改为 4?
如何在 Swift 4 中将 UIImage 转换为字节数组