74-Swift之Alamofire的基本使用和介绍(GET/POST)

前言

本篇是介绍Alamofire 的基本使用,对于还不会引入Alamofire的小伙伴可以看《73-Swift之Pods(CocoaPods)的Alamofire的引入的详细指导》

Alamofire 是啥?

Alamofire是自2014年Swift 推出之后,AFNetworking的作者 [Mattt Thompson] 便提交了一个新的类似于AFNetworking 的网络基础框架,并且是专门使用最新的Swift 语言来编写的,其名为:Alamofire

Alamofire 的优点

  • 链式的请求/响应方法(GET&POST等)
  • URLEncoding / JSONEncoding / PropertyListEncoding 参数编码
  • 上传类型支持:文件(File )、数据(Data )、流(Stream)以及MultipartFormData
  • 支持文件下载,下载支持断点续传
  • 支持使用NSURLCredential进行身份验证
  • HTTP响应验证validate()

Alamofire 对请求结果的解析方法提供如下

  • response 以请求DefaultDataResponse的对象返回请求结果。

  • responseData 这是将请求的结果以二进制流的形式解析。

  • responseJSON 这是将请求的结果以JSON的形式解析。

  • responseString 这是将请求的结果以字符串的形式解析。

  • responsePropertyList 这是将请求的结果以PLIST形式解析。

Alamofire 的GET请求方法和请求解析方法的介绍和使用

1、 无参数的Alamofire 的GET请求和解析方式的介绍

// MARK: Alamofire 的Get请求
func alamofireGet1() -> Void {
    /**
       该请求只有一个参数 'URLRequest',并返回请求对象(DataRequest)。我们可以处理请求对象(DataRequest)获取我们需要的数据。
     */
    let dataRequest:DataRequest = Alamofire.request("http://www.jianshu.com/u/23dd8d9701bf")
    
    // 输出请求返回的对象
    print(dataRequest)
    /**
     输出结果
     GET http://www.jianshu.com/u/23dd8d9701bf
     */
    
    // 解析请求的对象
    dataRequest.response { (DDResponse) in
        // 获取请求的状态码
        let stateCode = DDResponse.response?.statusCode
        print(stateCode!)
        
        // 获取请求的数据
        print(DDResponse.data!)// 只输出数据有多少字节数
        // 将数据转化为字符串
        let dataStr = String.init(data: DDResponse.data!, encoding:String.Encoding.utf8)
        print(dataStr!)
        
        // TODO: 输出请求对象
        let requestSwf = DDResponse.request
        print(requestSwf!)
        /*通过请求对象,我们可以获取请求的一系列信息*/
        // 请求头文件
        print(requestSwf?.allHTTPHeaderFields as Any)
        // 获取请求的缓存规则
        print(requestSwf?.cachePolicy as Any)
        // 获取请求体(body)
        print(requestSwf?.httpBody as Any)
        // 获取请求的方法
        print(requestSwf?.httpMethod as Any)
        
        
        // TODO: 输出请求响应对象
        let responseSwf = DDResponse.response
        print(responseSwf!)
        /**
         输出响应对象:
         <NSHTTPURLResponse: 0x608000221020> { URL: http://www.jianshu.com/u/23dd8d9701bf } { status code: 200, headers {
         "Cache-Control" = "max-age=0, private, must-revalidate";
         Connection = "keep-alive";
         "Content-Encoding" = gzip;
         "Content-Type" = "text/html; charset=utf-8";
         Date = "Sat, 30 Sep 2017 06:43:45 GMT";
         Etag = "W/\"663fd325a56556576a8facd92d50bedd\"";
         Server = Tengine;
         "Set-Cookie" = "_maleskine_session=Y1JTZ2xhYnZ6b3dMZnZaZmVQeHZqVFN5L2QyWDJmaURtcVVBNXFGSXhRWlMvTUxzUWRhTkRFdy83NVAzbW0yNHhqQ05KNkN1WFJTTURTSkNYVnkzYmV6Wm96bmZyVU1kY0VQK3l6bENwN1JUVmdEaGtVY2NBUEdjbzBCZjAvdGVDTWRvRkhlZG16c2tjOGUzSnRvTVVBQWNNYUZyazhNRXlWellNeFFnNHFISTZMQ213bzFKNzV5OEdkYjF5VGRKbE9HdUJtWGpqV0VKU1RNcVJ3TktnMEFjclhFdFRtS3dKYngzek9pM2dWbGcyMmtQc0dLRU1RbDk2bUN2WW9jd3N3OWNMeFFqRkMrK08vYU5aWklEakxIanc2T1k3WjNsbFB1OVF4Rmd1VFZ0b1p2SFZnQ3l0WVVmZFM1KzZ4YmEzNTFhcjhVNHE5K0dacDlsM3RtMDBRPT0tLWxWaTQwNGpwVmZVaHdjNnc3Rk9teUE9PQ%3D%3D--a78f5fd47ad6bf048e57fd6701649281b26b2c63; path=/; HttpOnly";
         "Transfer-Encoding" = Identity;
         "X-Content-Type-Options" = nosniff;
         "X-Frame-Options" = DENY;
         "X-Request-Id" = "33b02181-e572-423c-ac45-a373e55edd6b";
         "X-Runtime" = "0.078608";
         "X-Via" = "1.1 wdx18:10 (Cdn Cache Server V2.0)";
         "X-XSS-Protection" = "1; mode=block";
         } }
         */
        
        // TODO: 输出请求的错误信息
        print(DDResponse.error as Any)
        
        // TODO: 获取请求/响应统计信息的任务指标。
        print(DDResponse.metrics!)
    }
    
    // TODO: 以二进制数据形式输出请求结果(也可以说解析请求结果)
    dataRequest.responseData { (data) in
         print(data)
         /*输出:SUCCESS: 24039 bytes */
    }
    
    //TODO: 以JSON形式的输出请求数据(以JOSN形式解析结果)
    dataRequest.responseJSON { (dataResponse) in
        // 输出一个 'DataResponse' 的对象
        print(dataResponse)
        
        // 通过‘DataResponse’ 我们可以获取一些信息
        // 1.请求的连接
        print(dataResponse.request!)
        
        // 2. 请求响应的对象
        print(dataResponse.response!)
        
        // 3. 请求返回的数据
        print(dataResponse.data!)
        
        // 4. 服务器返回的结果
        print(dataResponse.result)
        
        // 5.完成请求需要的时间
        print(dataResponse.timeline)
    }
    
    //TODO: 将返回数据以字符串的形式解析
    dataRequest.responseString { (dataResponse) in
        // 输出一个 'DataResponse' 的对象
        print(dataResponse)
        
        // 通过‘DataResponse’ 我们可以获取一些信息
        // 1.请求的连接
        print(dataResponse.request!)
        
        // 2. 请求响应的对象
        print(dataResponse.response!)
        
        // 3. 请求返回的数据
        print(dataResponse.data!)
        
        // 4. 服务器返回的结果
        print(dataResponse.result)
        
        // 5.完成请求需要的时间
        print(dataResponse.timeline)
    }
    
    //TODO: 将数据以PLIST文件形式输出
    dataRequest.responsePropertyList { (dataResponse) in
        // 输出一个 'DataResponse' 的对象
        print(dataResponse)
        
        // 通过‘DataResponse’ 我们可以获取一些信息
        // 1.请求的连接
        print(dataResponse.request!)
        
        // 2. 请求响应的对象
        print(dataResponse.response!)
        
        // 3. 请求返回的数据
        print(dataResponse.data!)
        
        // 4. 服务器返回的结果
        print(dataResponse.result)
        
        // 5.完成请求需要的时间
        print(dataResponse.timeline)
    }
    
    //TODO: 在线程中处理请求的数据
    let dispathQu = DispatchQueue.main
    dataRequest.response(queue: dispathQu) { (ddataResponse) in
        // 返回一个‘DefaultDataResponse’ 对象
        print(ddataResponse)
        
        // 1、获取请求体
        print(ddataResponse.request!)
        
        // 2、获取请求响应体
        print(ddataResponse.response!)
        
        // 3、获取请求数据
        print(ddataResponse.data!)
        
        // 4、获取请求的错误信息
        print(ddataResponse.error!)
    }
    
    // 请求的进度
    print(dataRequest.progress)
}

2、Alamofire的带参数的GET请求

// TODO: Alamofire的GET请求带参数
func alamofireGet2() -> Void {
    let dataResponse = Alamofire.request("http://gc.ditu.aliyun.com/geocoding",parameters:["a":"北京"])
    // 请求返回的结果
    print(dataResponse)
    
    // 对请求的结果处理
    dataResponse.responseData { (dataRequ) in
        if let data = dataRequ.data {
            let strData = String.init(data: data, encoding: String.Encoding.utf8)
            print(strData!)
            /**
             输出的结果:
             {"lon":116.40752,"level":1,"address":"","cityName":"","alevel":4,"lat":39.90403}
             */
        }
    }
}

3、Alamofire的GET请求和返回数据一起处理的写法

// TODO: Alamofire的GET请求和返回数据一起处理的写法
func alamofireGet3() -> Void {
    Alamofire.request("http://gc.ditu.aliyun.com/geocoding",parameters:["a":"北京"]).responseString { (dataResquest) in
        if let data = dataResquest.data {
            let strData = String.init(data: data, encoding: String.Encoding.utf8)
            print(strData!)
            /**
             输出的结果:
             {"lon":116.40752,"level":1,"address":"","cityName":"","alevel":4,"lat":39.90403}
             */
        }
    }
}

Alamofire 的POST请求

// MARK: Alamofire的POST请求
func alamofirePost() -> Void {
    Alamofire.request("http://gc.ditu.aliyun.com/geocoding",method:.post ,parameters:["a":"北京"]).responseJSON { (dataRequest) in
        if let data = dataRequest.data {
            let strData = String.init(data: data, encoding: String.Encoding.utf8)
            print(strData!)
            /**
             输出的结果:
             {"lon":116.40752,"level":1,"address":"","cityName":"","alevel":4,"lat":39.90403}
             */
        }
    }
}

POST 和 GET 的友情快递

对于POST 和 GET的区别是:GET产生一个TCP数据包;POST产生两个TCP数据包。对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据); 而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 (返回数据)。

Alamofire 可以自定义请求

1、只定义请求方式的请求

// MARk:自定义请求
func customRequestMethod() -> Void {
    // 创建请求体
    let urlRequest = try! URLRequest.init(url: "http://www.jianshu.com/u/23dd8d9701bf", method: .get)
    Alamofire.request(urlRequest).responseString { (dataRequest) in
         print(dataRequest.data!)
    }
}
method 可选参数如下:
public enum HTTPMethod: String {
    case options = "OPTIONS"
    case get     = "GET"
    case head    = "HEAD"
    case post    = "POST"
    case put     = "PUT"
    case patch   = "PATCH"
    case delete  = "DELETE"
    case trace   = "TRACE"
    case connect = "CONNECT"
}

2、可是设置请求的缓存策略和请求超时的时间的请求

// MARK: 可是设置请求的缓存策略和请求超时的时间
func customRequestMethod1() -> Void {
    // 创建请求体
    let urlRequest =  URLRequest.init(url: URL.init(string: "http://www.jianshu.com/u/23dd8d9701bf")!, cachePolicy: .reloadIgnoringLocalAndRemoteCacheData, timeoutInterval: 30)
    Alamofire.request(urlRequest).responseData { (dataQuest) in
         print(dataQuest.data!)
    }
}

@ cachePolicy 是请求缓存策略参数
@ timeoutInterval 是请求超时时间参数

3、可设置请求方式和请求头的请求

// MARK: 可设置请求方式和请求头的请求
func customRequestMethod2() -> Void {
    // 创建请求体
    let urlRequest = try! URLRequest.init(url: "http://www.jianshu.com/u/23dd8d9701bf", method: .get, headers:["charset":"utf-8","Content-Type":"application/x-www-form-urlencoded","appKey":"NetWork小贱"])
    Alamofire.request(urlRequest).responseData { (dataRequest) in
         print(dataRequest.data!)
    }
}

@ method 设置请求方式
@ headers 设置请求头

Alamofire 的上传参数编码的请求

Alamofire 的请求参数编码有以下几种:

  • 1、 URLEncoding 是 “URL” 网址编码规则

  • 2、 JSONEncoding 是 “JSON” 格式编码规则

  • 3、 PropertyListEncoding 是 “PLIST” 文件编码规则

使用举例如下:

//MARK: 上传参数使用指定的编码格式上传的请求
func parameterCodingRequest() -> Void {
     // 请求的参数
    let parameter = ["type":"hot","offset":"0","limit":"10"]
    /**
     参数的所有编码形式如下,即 “ParameterEncoding” 的扩展对象:
     1、 URLEncoding  是 “URL” 网址编码规则
     2、 JSONEncoding 是 “JSON” 格式编码规则
     3、 PropertyListEncoding 是 “PLIST” 文件编码规则
     */
    Alamofire.request("http://m.maoyan.com/movie/list.json", method: .get, parameters: parameter,
                      encoding: URLEncoding.default).responseJSON { (dataRequest) in
                        if let data = dataRequest.data {
                            print(String.init(data: data, encoding: String.Encoding.utf8)!)
                        }
    }
}

Alamofire 的 validate() 函数的介绍

1、 validate() 函数是啥?

确认响应有默认可接受的200~299范围内的状态码,还有内容类型匹配在Accept HTTP头字段中指定的任何值。如果验证失败,随后对响应处理程序的调用将会有一个相关的错误。

2、请求信息的验证之 “validate”

// MARK: 请求信息的验证之 “validate”
func verifyInformationRequest() -> Void {
    Alamofire.request("http://m.maoyan.com/cinemas.json").validate().responseJSON { (dataRequest) in
        switch dataRequest.result.isSuccess {
        case true:
            let data  = dataRequest.data
            let dict = try! JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers)
            print(dict)
        case false:
            print("获取信息失败!!")
        }
    }
}

3、验证请求状态码在 “200~299” 之间的请求,否则,不验证。

// MARK: 验证请求状态码在 “200~299” 之间的请求,否则,不验证。
func requestStateCodeVerification() -> Void {
    Alamofire.request("http://m.maoyan.com/cinemas.json").validate(statusCode: [200,299]).responseJSON { (dataRequest) in
        switch dataRequest.result.isSuccess {
        case true:
            if let data = dataRequest.data {
                let dict = try! JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers)
                print(dict)
            }
        case false:
            print("获取信息失败!!!")
        }
    }
}

4、验证指定请求媒体信息格式的请求

// MARK: 验证指定请求媒体信息格式的请求
func verifyRequestMediaFormatRequest() -> Void {
    /**
     友情大爆炸:
     1、contentType : 即是 “Internet Media Type” 称之为 互联网媒体类型,也叫 “MIME”。作用是在 "HTTP" 请求头中使用“contentType”来指定不同格式的请求信息。
     
     2、contentType 常见的媒体格式类型如下:
     text/html  :HTML格式
     text/plain :纯文本格式
     text/xml   :XML格式
     image/gif  :gif图片格式
     image/jpeg :jpg图片格式
     image/png  :png图片格式
     以application开头的媒体格式类型:
     application/xhtml+xml :XHTML格式
     application/xml       :XML数据格式
     application/atom+xml  :Atom XML聚合格式
     application/json      :JSON数据格式
     application/pdf       :pdf格式
     application/msword    :Word文档格式
     application/octet-stream :二进制流数据(如常见的文件下载)
     application/x-www-form-urlencoded :<form encType=””>中默认的encType,form表单数据被编码为key/value格式发送到服务器(表单默认的提交数据的格式)
     */
    Alamofire.request("http://m.maoyan.com/cinemas.json").validate(contentType: ["text/html","text/plain","application/json"]).responseJSON { (dataRequest) in
        switch dataRequest.result.isSuccess {
        case true:
            if let data = dataRequest.data {
                let dict = try! JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers)
                print(dict)
            }
        case false:
            print("获取信息失败!!!")
        }
    }
}

5、我们可以根据某个条件,来设定返回的验证结果 “ValidationResult”

// MARK: 我们可以根据某个条件,来设定返回的验证结果 “ValidationResult”
func customizationValidationResult() -> Void {
    Alamofire.request("http://m.maoyan.com/cinemas.json").validate { (urlRequest, httpUrlResponse, data) -> Request.ValidationResult in
        // 在这里我们可以提前检验 请求的 “URLRequest”、“HTTPURLResponse” 和 返回的数据 “Data” 等来设置请求返回的 “ValidationResult”
        if !(urlRequest?.url?.absoluteString.contains("NetWork"))! {
            let error = NSError.init(domain: "m.maoyan.com", code: 320, userInfo: ["msg":"请求不包含指定的参数"]) as Error
            return Request.ValidationResult.failure(error)
        }
        return Request.ValidationResult.success
        }.responseJSON { (dataRequest) in
            switch dataRequest.result.isSuccess {
            case true:
                if let data = dataRequest.data {
                    let dict = try! JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers)
                    print(dict)
                }
            case false:
                let errorInfo = dataRequest.result.error! as NSError
                print(errorInfo.userInfo)
                /**
                 输出信息:["msg": "请求不包含指定的参数"]
                 */
            }
    }
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,524评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,869评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,813评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,210评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,085评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,117评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,533评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,219评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,487评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,582评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,362评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,218评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,589评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,899评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,176评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,503评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,707评论 2 335

推荐阅读更多精彩内容