美文网首页Swift AdvanceiOS DeveloperSwift
Alamofire从基础到进阶 基础请求与响应(一)

Alamofire从基础到进阶 基础请求与响应(一)

作者: Hellolad | 来源:发表于2018-03-30 19:17 被阅读276次

    Alamofire
    Version:4.5.1
    Swift Version: 4.0.3

    Podfiles

    # Uncomment the next line to define a global platform for your proje
    platform :ios, '8.0'
    target 'UseageAlamofire' do
      use_frameworks!
      pod 'Alamofire'
    end
    

    目录:
    Alamofire从基础到进阶 基础请求与响应(一)
    Alamofire从基础到进阶 小技巧(二)

    创建一个简单的Request

    let request = Alamofire.request("http://httpbin.org/ip")
    print("request = \(request)")
    输出:request = GET http://httpbin.org/ip
    

    上面的 GET 是请求类型,后面紧跟的就是你的请求的地址,还有另外两种创建一个Request的方式:

    • request(_ urlRequest: )
    • request(_ url:, method:, parameters:, encoding:, headers: )
      我们使用一下看看效果:
    let urlRequest = URLRequest(url: URL(string: "http://httpbin.org/ip")!)
    let request2 = Alamofire.request(urlRequest)
    print("request2 = \(request2)")
    输出:request2 = GET http://httpbin.org/ip
    
    let url = "http://httpbin.org/ip"
    let method: HTTPMethod = .get
    let parameters: Parameters = ["name": "chao"]
    let encoding: URLEncoding = .default
    let headers: HTTPHeaders = ["Content-Type": "application/json"]
    let request3 = Alamofire.request(url, method: method, parameters: parameters, encoding: encoding, headers: headers)
    print("request3 = \(request3)")
    输出:request3 = GET http://httpbin.org/ip?name=chao
    

    使用一下Response响应

    我们已经学会了用Alamofire创建一个Request,我们最终想要的是从服务器拿到数据,我们可以这样写:

    let url2 = "http://httpbin.org/ip"
    Alamofire.request(url2).response(completionHandler: { defaultResponse in
        print("request = ", defaultResponse.request)
        print("-----------------------------------")
        print("response = ", defaultResponse.response)
        print("-----------------------------------")
        print("data = ", defaultResponse.data)
        print("-----------------------------------")
        print("error = ", defaultResponse.error)
        print("-----------------------------------")
        print("metrics = ", defaultResponse.metrics)
        print("-----------------------------------")
        print("timeline = ", defaultResponse.timeline)
    })
    

    输出:

    response =  Optional(<NSHTTPURLResponse: 0x60000002ff00> { URL: http://httpbin.org/ip } { Status Code: 200, Headers {
        "Access-Control-Allow-Credentials" =     (
            true
        );
        "Access-Control-Allow-Origin" =     (
            "*"
        );
        Connection =     (
            "keep-alive"
        );
        "Content-Length" =     (
            32
        );
        "Content-Type" =     (
            "application/json"
        );
        Date =     (
            "Fri, 30 Mar 2018 10:41:03 GMT"
        );
        Server =     (
            "meinheld/0.6.1"
        );
        Via =     (
            "1.1 vegur"
        );
        "X-Powered-By" =     (
            Flask
        );
        "X-Processed-Time" =     (
            0
        );
    } })
    -----------------------------------
    data =  Optional(32 bytes)
    -----------------------------------
    error =  nil
    -----------------------------------
    metrics =  Optional((Task Interval) <_NSConcreteDateInterval: 0x600000030e40> (Start Date) 2018-03-30 10:41:03 +0000 + (Duration) 0.677700 seconds = (End Date) 2018-03-30 10:41:03 +0000
    (Redirect Count) 0
    (Transaction Metrics) (Request) <NSURLRequest: 0x600000012b60> { URL: http://httpbin.org/ip }
    (Response) <NSHTTPURLResponse: 0x60000002f580> { URL: http://httpbin.org/ip } { Status Code: 200, Headers {
        "Access-Control-Allow-Credentials" =     (
            true
        );
        "Access-Control-Allow-Origin" =     (
            "*"
        );
        Connection =     (
            "keep-alive"
        );
        "Content-Length" =     (
            32
        );
        "Content-Type" =     (
            "application/json"
        );
        Date =     (
            "Fri, 30 Mar 2018 10:32:49 GMT"
        );
        Server =     (
            "meinheld/0.6.1"
        );
        Via =     (
            "1.1 vegur"
        );
        "X-Powered-By" =     (
            Flask
        );
        "X-Processed-Time" =     (
            0
        );
    } }
    (Fetch Start) 2018-03-30 10:41:03 +0000
    (Domain Lookup Start) (null)
    (Domain Lookup End) (null)
    (Connect Start) (null)
    (Secure Connection Start) (null)
    (Secure Connection End) (null)
    (Connect End) (null)
    (Request Start) 2018-03-30 10:41:03 +0000
    (Request End) 2018-03-30 10:41:03 +0000
    (Response Start) 2018-03-30 10:41:03 +0000
    (Response End) 2018-03-30 10:41:03 +0000
    (Protocol Name) (null)
    (Proxy Connection) NO
    (Reused Connection) YES
    (Fetch Type) Local Cache
    
    (Request) <NSURLRequest: 0x600000012a10> { URL: http://httpbin.org/ip }
    (Response) <NSHTTPURLResponse: 0x60000002fb60> { URL: http://httpbin.org/ip } { Status Code: 200, Headers {
        "Access-Control-Allow-Credentials" =     (
            true
        );
        "Access-Control-Allow-Origin" =     (
            "*"
        );
        Connection =     (
            "keep-alive"
        );
        "Content-Length" =     (
            32
        );
        "Content-Type" =     (
            "application/json"
        );
        Date =     (
            "Fri, 30 Mar 2018 10:41:03 GMT"
        );
        Server =     (
            "meinheld/0.6.1"
        );
        Via =     (
            "1.1 vegur"
        );
        "X-Powered-By" =     (
            Flask
        );
        "X-Processed-Time" =     (
            0
        );
    } }
    (Fetch Start) 2018-03-30 10:41:03 +0000
    (Domain Lookup Start) 2018-03-30 10:41:03 +0000
    (Domain Lookup End) 2018-03-30 10:41:03 +0000
    (Connect Start) 2018-03-30 10:41:03 +0000
    (Secure Connection Start) (null)
    (Secure Connection End) (null)
    (Connect End) 2018-03-30 10:41:03 +0000
    (Request Start) 2018-03-30 10:41:03 +0000
    (Request End) 2018-03-30 10:41:03 +0000
    (Response Start) 2018-03-30 10:41:03 +0000
    (Response End) 2018-03-30 10:41:03 +0000
    (Protocol Name) http/1.1
    (Proxy Connection) NO
    (Reused Connection) NO
    (Fetch Type) Network Load
    
    )
    -----------------------------------
    timeline =  Timeline: { "Latency": 0.677 secs, "Request Duration": 0.678 secs, "Serialization Duration": 0.000 secs, "Total Duration": 0.678 secs }
    

    上面输出了很多很多的东西,我们来具体看看都有什么?
    DefaultDataResponse
    这个响应结果是Alamofire提供的一个结构体,我们看一下源码:

    /// The URL request sent to the server.
    public let request: URLRequest?
    
    /// The server's response to the URL request.
    public let response: HTTPURLResponse?
    
    /// The data returned by the server.
    public let data: Data?
    
    /// The error encountered while executing or validating the request.
    public let error: Error?
    
    /// The timeline of the complete lifecycle of the request.
    public let timeline: Timeline
    
    var _metrics: AnyObject?
    

    DefaultDataResponse结构体定义了上面这几个属性:
    reqeuest就是你定义的请求
    reponse是响应结果
    data是服务器返回给我们的数据
    error是执行请求和验证结果时候的错误
    timeline是该请求从请求到收到结果的一条时间线
    _metrics是iOS10及以后提供的一个时间线的属性,和timeline大同小异,所以你要使用的话必须是支持iOS10以后的版本才能使用

    /// 这样写就没有问题了
    if #available(iOS 10, *) {
        print("metrics = ", defaultResponse.metrics)
    }
    

    不过除了response响应处理以外我们还有4种其他的响应处理方式:

    • responseJSON
    • reponseData
    • responseString
    • responsePropertyList

    在我们的程序里,大多数用到的是第一和第二种。
    responseString响应处理的是字符串
    responsePropertyList响应处理的是plist(类似于responseJSON)都是转换成Any类型。
    responseJSON是将服务器返回数据序列化为json然后转换成Any.
    reponseData是将服务器返回数据序列化为Data然后转换成Data.

    Alamofire强烈建议我们使用这四种去做处理,不建议我们使用DefaultResponse,这个就不纠结了我们用下面四种已经足够了。

    先看responseData:

    Alamofire.request(url2).responseData(completionHandler: { response in
        print(response.result.value)
    })
    输出:Optional(32 bytes)
    

    我们看到了reponse.result,这个result是啥?我们点进去看看

    enum Result<Value> {
        case success(Value)
        case failure(Error)
    
        public var value: Value? {
            switch self {
            case .success(let value):
                return value
            case .failure:
                return nil
            }
        }
    }
    /// 源码我没有展示完 我们只看关于这篇文章的
    

    Reust是一个泛型的枚举,当我们使用responseData的使用,Value就会被转换为Data,当我们调用response.result.vlaue的时候就会看到输出了"Optional(32 bytes)"这很明显是Data类型,然后我们把它解析出来看看是什么:

    let url2 = "http://httpbin.org/ip"
    Alamofire.request(url2).responseData(completionHandler: { response in
        guard let value = response.result.value else { return }
        let result = try? JSONSerialization.jsonObject(with: value, options: [])
        guard let res = result else { return }
        let dictionary = res as! [String: Any]
        print("dictionary = ", dictionary)
    })
    输出:dictionary =  ["origin": 101.81.57.239]
    

    这就是responseData的简单用法了.
    下面我们来看responseJSON怎么使用:

    Alamofire.request(url2).responseJSON { response in
         print(response.result.value)
    }
    输出: Optional({ origin = "101.81.57.239";})
    

    很明显它是一个JSON格式,这就是Alamofire序列化为JSON的好处。为什么我们使用Reulst,因为它是Alamofire序列化好服务器给我们使用的一个属性,所以我们不用再去做序列化的操作,直接使用就好了。下面我们转化成字典类型:

    Alamofire.request(url2).responseJSON { response in
        guard let value = response.result.value else { return }
        let dictionary = value as! [String: Any]
        print("dictionary = ", dictionary)
    }
    输出:dictionary =  ["origin": 101.81.57.239]
    

    和responseData是一样的输出结果,但是比responseData要少两步, 所以如果你的程序后台返回的是JSON格式的数据,你直接使用responseJSON要比responseData要方便很多。

    --以此来记录 Usage Alamofire ^ _^ --

    相关文章

      网友评论

      • ing_69c7:把HTTPHeaders单提出来说一下就更好了 我们服务器就不支持文章中的格式 需要改成 let headers: HTTPHeaders = ["Content-Type": "application/x-www-form-urlencoded; charset=utf-8"]
        Hellolad:["Content-Type": "application/x-www-form-urlencoded; charset=utf-8"] 是Post请求的时候才会使用到的,如果你使用Alamofire时,不用加这个Content-type这个key,因为Alamofire是这样判断的。
        if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil {
        urlRequest.setValue("application/x-www-form-urlencoded; charset=utf-8", forHTTPHeaderField: "Content-Type")
        }所以你压根就不用加,我说的是你使用Alamofire的情况下。

      本文标题:Alamofire从基础到进阶 基础请求与响应(一)

      本文链接:https://www.haomeiwen.com/subject/bovicftx.html