美文网首页
上手Alamofire处理HTTP请求

上手Alamofire处理HTTP请求

作者: 醉看红尘这场梦 | 来源:发表于2020-03-12 09:20 被阅读0次

向大家介绍Alamofire的基本用法,即如何通过iOS客户端发起各种HTTP请求,并以Alamofire提供的不同方式处理HTTP response。为了简单起见,在我们的例子里,Alamofire的应用都不会和UI代码相关,我们只演示HTTP通信的部分。首先,我们从一个最简单的HTTP请求开始。


发起一个最基本的HTTP请求

打开AlamoFireDemo的ViewController.swift文件,添加下面的代码:


import UIKit
import Alamofire

"引入"了Alamofire module之后,我们就可以使用它提供的各种API了。为了测试各种HTTP action,我们需要一个与之配合的服务端程序。幸运的是,至少现在我们还不用专门去写它,httpbin.org为我们提供了方便的HTTP测试API:

image

包括GET一个页面、一个JSON、各种REST方法、常用的HTTP status、认证、下载等。它们可以很方便的让我们来测试Alamofire提供的各种功能。我们从GET /ip开始,httpbin会返回一个类似下面这样的JSON:


{
    "origin": "106.185.45.242"
}

回到Xcode,在viewDidLoad()里,添加下面的代码:


override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    Alamofire.request(.GET, "https://httpbin.org/ip")
}

这样,我们就完成了一次对httpbin.org的GET请求。看似简单,却有三点需要说明:

第一点是Alamofire.request这样的用法,该如何理解呢?Alamofire是类名吗?request是一个class method吗?实际上不是这样的。前面的Alamofire是因为我们一开始引入了Alamofire module之后,开启的名字空间;而request则是这个名字空间里的一个函数,我们可以在Alamofire的源代码里找到它。

第二点是request的第一个参数,表示我们采用的HTTP方法。它是Alamofire定义的一个enum,在这里


public enum Method: String {
    case OPTIONS, GET, HEAD, POST, PUT, PATCH, DELETE, TRACE, CONNECT
}

第三点是Alamofire发起的HTTP request是和App主线程并行执行的,它并不会阻塞App的UI。

理解了这三点,上面的代码就没有任何问题了。接下来,我们来看如何处理HTTP response。


处理HTTP response

Alamofire有一个最原始的获取HTTP response的方法,像这样:


override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    Alamofire.request(.GET, "https://httpbin.org/ip")
        .response { request, response, data, error in 
            print(request)
            print(response)
            print(data)
            print(error)
        }
}

image

从图中的结果就可以看到closure的四个参数对应的类型了,它们分别代表request/response的基本信息,返回内容的原始数据以及错误信息。事实上,如果我们查看response的实现,就会发现更多内容:


public func response(
    queue queue: dispatch_queue_t? = nil,
    completionHandler: 
        (NSURLRequest?, 
         NSHTTPURLResponse?, 
         NSData?, 
         NSError?) -> Void)
    -> Self
{
    delegate.queue.addOperationWithBlock {
        dispatch_async(queue ?? dispatch_get_main_queue()) {
            completionHandler(self.request, 
                self.response, 
                self.delegate.data, 
                self.delegate.error)
        }
    }

    return self
}

response实际上有2个参数,只不过第一个参数有默认值,所以,我们使用了一个trailing closure定义了它的第二个参数。当第一个参数queue为nil时,Alamofire默认会在App的主线程中执行我们的handler,方便我们在收到HTTP请求的时候更新UI。

当我们通过这种方式得到了一个表示HTTP response的NSData对象后,我们就可以把它变成Image、序列化成JSON等等。但是如果真是这样,我们就完全没必要使用Alamofire了,因为这几乎和NSURLSession的"套路"是一样的。实际上,我们很少直接使用这个原始的response,Alamofire为我们提供了更方便的序列化结果的方法:


responseData(/*completionHandler*/)
responseString(encoding: NSStringEncoding, 
    /*completionHandler*/)
responseJSON(options: NSJSONReadingOptions, 
    /*completionHandler*/)
responsePropertyList(options: NSPropertyListReadOptions, 
    /*completionHandler*/)

image

它们之中,后三个方法的第一个参数可以先暂时忽略,因为它们都是有默认值的。这四个方法的共同之处就是它们有一个共同的handler,这个handler接受一个类型为Response<nsdata, nserror="" style="box-sizing: border-box;">的参数,用来让我们在Alamofire完成序列化之后,做进一步的处理。</nsdata,>

而我们查看Response的源代码就会发现,它封装了之前我们用过的request / response / data:


public struct Response {
    /// The URL request sent to the server.
    public let request: NSURLRequest?

    /// The server's response to the URL request.
    public let response: NSHTTPURLResponse?

    /// The data returned by the server.
    public let data: NSData?

    /// The result of response serialization.
    public let result: Result

    // Omit for simplicity...
}

并且,它还额外提供了一个Result<value, error="" style="box-sizing: border-box;">类型的属性result,方便我们读取序列化过之后的结果(简单起见,例子中省略了实现的部分):</value,>


public enum Result {
    case Success(Value)
    case Failure(Error)

    public var isSuccess: Bool {
        // Omit for simplicity...    
    }

    public var isFailure: Bool {
        // Omit for simplicity...   
    }

    public var value: Value? {
        // Omit for simplicity...
    }

    public var error: Error? {
        // Omit for simplicity...
    }
}

另外,Result还实现了CustomStringConvertible protocol,我们可以直接print一个Result对象。

在理解了这些处理HTTP response的类型之后,我们就可以很方便的处理Alamofire返回的序列化结果了。


处理序列化之后的String和JSON

首先来看String:


Alamofire.request(.GET, "https://httpbin.org/ip")
    .response { request, response, data, error in
        print(request)
        print(response)
        print(data)
        print(data.dynamicType)
        print(error)
        print(error.dynamicType)
    }
    .responseString { response in
        print("String:====================")

        switch response.result {
        case .Success(let str):
            print("\(str.dynamicType)")
        case .Failure(let error):
            print("\(error)")
        }
    }

在这里,Alamofire的各种response方法是可以串联在一起的,由于response.result是一个enum,我们可以通过一个switch...case来处理它的两种结果,并且在.Success里,直接读取它的associated value作为返回的字符串;在.Failure里读取包含错误信息的对象。

image

接下来,我们来看JSON。为了得到一个相对复杂一些的JSON,这次,我们请求httpbin的/get,然后,会得到一个类似下面的返回结果:


{
  "args": {}, 
  "headers": {
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", 
    "Accept-Encoding": "gzip, deflate, sdch", 
    "Accept-Language": "en-US,en;q=0.8,zh-CN;q=0.6,zh;q=0.4", 
    "Cookie": "_ga=GA1.2.1123360294.1453608486; _gat=1", 
    "Host": "httpbin.org", 
    "Referer": "https://httpbin.org/", 
    "Upgrade-Insecure-Requests": "1", 
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2646.0 Safari/537.36"
  }, 
  "origin": "106.185.45.242", 
  "url": "https://httpbin.org/get"
}

首先我们把之前例子里的请求的URL修改成https://httpbin.org/get


Alamofire.request(.GET, "https://httpbin.org/get") 

然后,把responseJSON串联在responseString后面:


Alamofire.request(.GET, "https://httpbin.org/get")
    .responseString(completionHandler: { response in
        print("String ===============")

        switch response.result {
        case .Success(let str):
            print("\(str.dynamicType)")
            print("\(str)")
        case .Failure(let error):
            print("\(error)")
        }
    })
    .responseJSON(completionHandler: { response in
        print("JSON ================")

    })

为了更好的理解解析JSON的方式,我们来看个图:

image

对于一个JSON的返回结果来说,它的所有KEY的类型,都是String,而VALUE的类型,有可能是一个String值,有可能是一个数组,还有可能是一个对象。因此,Alamofire只能用一个AnyObject类型的对象表示它。通常,我们要把它转化成一个<key style="box-sizing: border-box;">NSDictionary</key>或Dictionary<String, AnyObject>类型的对象。然后,根据访问的KEY的类型,做进一步的类型转换:

  • 读取key1时,把结果转化成String
  • 读取key2时,把结果转化成Array
  • 读取key3时,把结果转化成其它的Dictionary

理解了处理JSON的方法,我们就可以在responseJSON中处理httpbin的返回结果了:


Alamofire.request(.GET, "https://httpbin.org/get")
    .responseJSON(completionHandler: { response in
        print("JSON ================")

        switch response.result {
        case .Success(let json):
            let dict = json as! Dictionary
            let origin = dict["origin"] as! String
            let headers = dict["headers"] as! Dictionary

            print("origin: \(origin)")
            let ua = headers["User-Agent"]
            print("UA: \(ua)")
        case .Failure(let error):
            print("\(error)")
        }
    })

在上面的代码中我们可以看到,在读取"origin"和"headers"时,我们并不用类型转换,并且,在下面的结果里,变量origin和ua各自代表了JSON中的内容:

image

相关文章

  • 上手Alamofire处理HTTP请求

    向大家介绍Alamofire的基本用法,即如何通过iOS客户端发起各种HTTP请求,并以Alamofire提供的不...

  • swift常用第三方库

    网络Alamofire:http网络请求事件处理的框架。Moya:这是一个基于Alamofire的更高层网络请求封...

  • Swift常用第三方库

    网络 Alamofire: http网络请求事件处理的框架。 Moya: 这是一个基于Alamofire的更高层网...

  • 一些好用swift三方框架

    网络 Alamofire:http网络请求事件处理的框架。 Moya:这是一个基于Alamofire的更高层网络请...

  • swift 三方库

    网络 Alamofire:http网络请求事件处理的框架。 Moya:这是一个基于Alamofire的更高层网络请...

  • Swift相关第三方资源整合

    网络 Alamofire:http网络请求事件处理的框架。 Moya:这是一个基于Alamofire的更高层网络请...

  • Swift常用第三方库

    网络 Alamofire:http网络请求事件处理的框架。 Moya:这是一个基于Alamofire的更高层网络请...

  • swift第三方

    网络 Alamofire:http网络请求事件处理的框架。 Moya:这是一个基于Alamofire的更高层网络请...

  • Swift相关第三方资源整合

    网络 Alamofire:http网络请求事件处理的框架。 Moya:这是一个基于Alamofire的更高层网络请...

  • Swift常用第三方

    网络 Alamofire:http网络请求事件处理的框架。 Moya:这是一个基于Alamofire的更高层网络请...

网友评论

      本文标题:上手Alamofire处理HTTP请求

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