在 Swift 3 中从 URLSession 迁移到 Alamofire 4.3,编码问题

Posted

技术标签:

【中文标题】在 Swift 3 中从 URLSession 迁移到 Alamofire 4.3,编码问题【英文标题】:Migrating from URLSession to Alamofire 4.3 in Swift 3, Encoding issue 【发布时间】:2017-02-20 09:01:30 【问题描述】:

Alamofire 4.3,Swift 3中下面的等价代码是什么?

let baseUrl = "https://hiddenWebsite.com/api/index_load"
let url = URL(string: baseUrl)
let authObj = ["owner_id": "361900", "auth_key": "f408634ac1e14c08eebce46c34ab9db2", "device": "2", "version": "2.1.16"]
let infoObj = ["case": "feeds", "feeds_call_type": "init", "feed_type": "", "load_next_from": "1"]

let infoJSONData = try! JSONSerialization.data(withJSONObject: infoObj)
let infoStr = "info" + "=" + String(data: infoJSONData, encoding: String.Encoding.utf8)!

let authJSONData = try! JSONSerialization.data(withJSONObject: authObj)
let authStr = "auth" +  "=" + String(data: authJSONData, encoding: String.Encoding.utf8)!

let combinedStr = infoStr  +  "&" + authStr
let reqdat = combinedStr.data(using: String.Encoding.utf8)

var request = URLRequest(url: url!)
request.httpMethod = "POST"
request.httpBody = reqdat
let defaultSession = URLSession.shared
defaultSession.dataTask(
    with: request,
    completionHandler:  data, response, error in
        guard error == nil else 
            print("Error while fetching data: \(error)")
            return
        
        guard let data = data,
            let json = try? JSONSerialization.jsonObject(
                with: data,
                options: JSONSerialization.ReadingOptions.mutableContainers)
            else 
                print("Nil data received")
                return
        
        print(json)
).resume()

我目前正在从 Apple 的 URLSession 迁移到 Alamofire,但停留在这一点上。我认为这与 encodingParameter 有关。 这是我失败的尝试。我也尝试过使用 URLEncoding.httpbody 但没有用。

    let baseUrl = "https://hiddenWebsite.com/api/index_load"
    let masterParameter = [
        "auth": ["owner_id": "361900",
                 "auth_key": "f408634ac1e14c08eebce46c34ab9db2",
                 "device": "2",
                 "version": "2.1.16"],
        "info": ["case": "feeds",
                 "feeds_call_type": "init",
                 "feed_type": "",
                 "load_next_from": "1"]
    ]
    Alamofire.request(baseUrl, method: .post, parameters: masterParameter, encoding: JSONEncoding.default).responseJSON  (response) in

        print(response)
    

相当于这个的工作邮递员看起来像 Postman Screenshot

【问题讨论】:

【参考方案1】:

您使用的编码不是有效的 JSON。因此,您不能使用 JSON.default 作为编码类型,因为它会将您的 masterParameter 字典编码为有效的 JSON 字典。

相反,您需要像在第一个示例中所做的那样手动构建您的URLRequest 并使用Alamofire.request(urlRequest) API,或者您可以创建自己的ParameterEncoding,将您的数据传递给它,然后编码URLRequest.

【讨论】:

【参考方案2】:

感谢cnoon 的回答。下面的代码解决了这个问题:

public enum JSONError: Error 
    case serializing(String)
    case encoding


extension String: ParameterEncoding 
    public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest 
        var request = try urlRequest.asURLRequest()
        request.httpBody = self.data(using: String.Encoding.utf8)
        return request
    


let encodedStr = try getEncodedString(parameters: masterParameter)
Alamofire.request(baseUrl, method: .post, parameters: [:], encoding: encodedStr).responseJSON  response in
        print(response)

其中 getEncodedString(parameters:) 定义为:

func getEncodedString(parameters: Parameters) throws -> String 

        var encodedStr = ""
        for (key, value) in parameters 

            let jsonData: Data
            do 
                jsonData = try JSONSerialization.data(withJSONObject: value)
            
            catch(let error) 
                throw JSONError.serializing(error.localizedDescription)
            
            guard let encodedJsonString = String(data: jsonData, encoding: .utf8) else 
                throw JSONError.encoding
            
            let keyValueStr = key + "=" + encodedJsonString
            encodedStr += keyValueStr + "&"
        
        if encodedStr.characters.last == "&" 
            encodedStr.remove(at: encodedStr.index(before: encodedStr.endIndex))
        

        return encodedStr
    

【讨论】:

以上是关于在 Swift 3 中从 URLSession 迁移到 Alamofire 4.3,编码问题的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Swift 3 中使用带有代理的 URLSession

Swift 3,未调用 URLSession 数据任务完成处理程序

将 URLSession 更新为 swift 3 抛出错误

如何在从 Swift 3 中的函数返回结果之前等待 URLSession 完成

从 URLSession 完成处理函数 Swift 3 返回字符串

在 swift 3 中下载文件最多只能完成 24 kb?使用 URLSession