swift之网络请求框架Alamofire

参考原码解析:https://www.cnblogs.com/machao/p/6856603.html

安装使用参考一:http://blog.csdn.net/codingfire/article/details/51940212

安装使用参考二:https://www.jianshu.com/p/42aa9b5b70a3

原码解读:https://www.cnblogs.com/machao/p/6640248.html?utm_source=tuicool&utm_medium=referral

官网:https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#http-methods

原码解析:https://www.jianshu.com/p/f39ad2a3c10b

使用参考:https://www.jianshu.com/p/f8c3adb056cf、https://www.jianshu.com/p/903b678d2d3f

参考使用:https://github.com/WangLiquan/EWAlamofireEncapsulation

https://www.jianshu.com/p/c3980b4c07c5

==============get、post请求的简单封装=========

/**
 网络请求中心 get post请求
 使用:
 let loginhttp:LYBHttpManager=LYBHttpManager()
 let paramas:[String:String]=["username":"133355" ,"password":"11111"]
 let url:String="\(BASEURL)"+"index.php?m=Api&c=User&a=login"
 loginhttp.requestWithJson(url: url, httpMethod: .get, params: paramas, success: { (res) in
 
 if  ((res["result"]) != nil) {//判断res中是否存在result这个键
 let resultDict=res["result"] as? NSDictionary
 let  loginresultModel=LYBLoginResultModel.deserialize(from: resultDict)//这是根据字典转模型,还可以直接字符串转模型
 LYBLoginVC.model=loginresultModel//静态变量存储,整个程序生命周期期间且所有类中都可以用
 print("\(String(describing: loginresultModel?.token))")
 }else{
 print("没有")
 }
 
 }) { (error) in
 //返回的错误
 let s = String.init(describing: error)// 吧返回的错误转换成字符串
 MBProgressHUD.showError(s)
 }
 }
 */

import UIKit

class LYBHttpManager: NSObject,URLSessionDelegate,URLSessionDataDelegate {
   //*******注意自定义的manager必须是强引用,否则请求结果都是code=-999 cancelled
    
    static  var manager: SessionManager?=nil
    /**
     SessionManager的配置和创建
     
     */
  func createManage(){
        let config:URLSessionConfiguration = URLSessionConfiguration.default
        //创建httpHeader
        var defaultHeaders = Alamofire.SessionManager.defaultHTTPHeaders
        //给httpheader添加内容
//        defaultHeaders["token"] = "token的内容"
//        defaultHeaders["Authorization"] = ""
        defaultHeaders.updateValue("application/json", forKey: "Accept")
        config.httpAdditionalHeaders = defaultHeaders
//     config.httpAdditionalHeaders=[:]//http请求头,或者直接这样写
        //配置证书验证
//        let serverTrustPolicies: [String: ServerTrustPolicy] = [
//            ///正式环境的证书配置,修改成自己项目的正式url
//            "www.baidu.com": .pinCertificates(
//                certificates: ServerTrustPolicy.certificates(),
//                validateCertificateChain: true,
//                validateHost: true
//            ),
//            //测试环境的证书配置,不验证证书,无脑通过
//            "192.168.1.213:8002": .disableEvaluation,
//            ]
        config.timeoutIntervalForRequest = 20

        config.httpMaximumConnectionsPerHost=5;//最大连接数

//       //根据config创建manager-----带验证域名
//         LYBHttpManager.manager = Alamofire.SessionManager(configuration: config,
//                              delegate: SessionDelegate(),
//                              serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies))


        //根据config创建manager-----不验证域名
    LYBHttpManager.manager = Alamofire.SessionManager(configuration: config)
    }
   
  
//========================================
    /**
     核心的方法:get  post请求,返回的是json数据
     pamara1: 请求的地址
     parama2:.get  .post
     parama3:参数
     parama4:成功的回调
     parama5:失败的回调
     */
    public func requestWithJson(url: String,
                            httpMethod: HTTPMethod,
                            params: Dictionary?,
                            success: @escaping success,
                            failure: @escaping failure){
createManage()//配置创建sessionmanager
        if httpMethod == HTTPMethod.get{
            LYBHttpManager.manager!.request(url,
    method: .get,
        parameters: params,
        encoding: URLEncoding.default,
    headers: nil).responseJSON {
            (response) in
//        print("\(response)")
        /*这个的结果(前面有一层SUCCESS,可以用response.result.value取到服务器返回的数据)----SUCCESS: {
        msg = "\U767b\U9646\U6210\U529f";
        result =     {agent = 0;};
         status = 1;
            }*/
//         print("\(response.result)")//结果是SUCCESS或者
//        print("\(response.result.value)")//服务器返回的数据
  switch response.result{
    case .success(let data)://这里的data就是response的数据
     
        if let value = response.result.value as? Dictionary{//吧返回的数据转换成字典
        ///添加一些全部接口都有的一些状态判断
        if value["status"] as! Int == 1010 {
                        return
            }
        
      success(value as NSDictionary)
        }
    case .failure(let err)://这里的err就是网路链接失败返回的数据
        failure(err as AnyObject)
    
            }
        }
    }
    else{
    //post
            LYBHttpManager.manager!.request(url,method: .post,parameters: params!,
    encoding: JSONEncoding.default,
            headers: nil).responseJSON { (response) in
                
                 success(response as AnyObject)
        switch response.result{
            case .success:
            ///添加一些全部接口都有的一些状态判断
            if let value = response.result.value as? Dictionary {
            if value["status"] as! Int == 1010 {
                success(value as AnyObject)
                    return
                        }
        success(value as NSDictionary)
                                    }
        case .failure(let err):
                failure(err as AnyObject)
            break
            }
            }
        }
    }
    
}

 

===========

 

Alamofire进行Https网络请求自签名证书:https://www.jianshu.com/p/1005ce8fec8e

 let url="\(BASEURL)"+LUNBOURL

    let image:UIImage=UIImage.init(named:"bannerhomeOne")!

    //获取数据

    func normalGetData()  {

 

 //get--01--response

 

    Alamofire.request(url).response { (returnResult)in

    if let data = returnResult.data,let utf8Text =String(data: data, encoding: .utf8) {

    print(" utf8Text =\(utf8Text)")

    }

    }

      

//    get--02---responseData

        Alamofire.request(url).responseData { (returnResult)in

            debugPrint(" returnResult =\(returnResult)")

            if let data = returnResult.data,let utf8Text =String(data: data, encoding: .utf8) {

                print(" utf8Text =\(utf8Text)")

            }

        }

        

        

  //get--03--responseString

        Alamofire.request(url).responseString { (returnResult)in

            debugPrint(" Sucess =\(returnResult.result.isSuccess)")

            print(" returnResult =\(returnResult)")

        }

        

        

   //get --04--responseJSON

        Alamofire.request(url).responseJSON { (returnResult)in

            debugPrint("responseJSON -->\(returnResult)")

            if let json = returnResult.result.value {//这个转换的json数据比较正规

                print("responseJSON -->\(json)")

                /*  返回请求地址、数据、和状态结果等信息

                 print(" responseJSON() --> \(returnResult.request!)")

                 print("responseJSON() --> \(returnResult.data!)")

                 print(" responseJSON() --> \(returnResult.result)")

                 */

            }

        }

        

        

//        get--05---queue

//         补充:1.参数:queue:请求队列 --> 就是默认在主线程中执行~我们可以自定义调度队列。

//         官方解释:Response handlers by default are executed on the main dispatch queue. However, a custom dispatch queue can be provided instead.

       

        let customQueue = DispatchQueue.global(qos: .utility)

        Alamofire.request(url).responseJSON(queue: customQueue) { (returnResult)in

            print("请求队列 -->\(returnResult)")

        }

    

    

   //get---06带请求头设置获取数据

            

                let headers: HTTPHeaders = [

                    "Accept":"application/json"//设置客户端以什么格式解析服务器返回的数据

                ]

                Alamofire.request(url, headers: headers).responseJSON { (returnResult)in

                    print("获取数据并设置请求头 --> returnResult =\(returnResult)")

                }

            }

   

    

    

  //GET请求---无参数

    func getData()  {

        Alamofire.request(url, method: .get).responseJSON { (returnResult)in

            print("GET 请求无参数 --> returnResult =\(returnResult)")

        }

    }

  

  

 //POST请求----无参数

    func postData(){

        Alamofire.request(url, method: .post).responseJSON { (returnResult)in

            print("POST 请求无参数 --> returnResult =\(returnResult)")

        }

    }

    

 

 //POST请求有参数

    func postDataWithParams() {

        let param = [String:String]()

        Alamofire.request(url, method: .post, parameters: param).responseJSON { (returnResult)in

            print(" POST 请求有参数参数 --> returnResult =\(returnResult)")

        }

    }

    

 

    

 //   URLRequest的方式请求

    func URLRequestWidth() {

 

        let urls = URL(string: url)

        var urlRequest = URLRequest(url: urls!)

        urlRequest.httpMethod = "POST"

                let param = ["type":"","key":""]

                do {

                    urlRequest.httpBody = try JSONSerialization.data(withJSONObject: param, options: [])

                } catch {

                    print(error)

                }

 

        urlRequest.setValue("application/json", forHTTPHeaderField:"Content-Type")

        Alamofire.request(urlRequest).responseData { (returnResult)in

            debugPrint(returnResult)

            if let data = returnResult.data,let utf8Text = String(data: data, encoding: .utf8) {

                print(" URLRequest请求方式 --> utf8Text =\(utf8Text)")

            }

        }

    }

    

    

//下载不带进度

    func download() {

        // 1.下载图片

        Alamofire.download(url).responseData { (returnResult)in

            if let data = returnResult.result.value {

                let image = UIImage(data: data)

                print("image =\(image!)")

            } else {

                print("下载失败")

            }

        }

 

    }

    

 //下载带进度

    func downoadWithProgress() {

 

    Alamofire.download(url).downloadProgress { (progress)in

    print("下载进度 =\(progress.fractionCompleted)")

    }.responseData { (returnResult) in

    if let data = returnResult.result.value {

    let image = UIImage(data: data)

    print("image =\(image!)")

    } else {

    print("下载失败")

    }

    }

    }

    

 //uploadData----上传data数据

    func uploadData()  {

 

        let imageData =UIImagePNGRepresentation(image)!

        Alamofire.upload(imageData, to: url).responseJSON { response in

            debugPrint(response)

        }

    }

 

 //uploadFile----上传文件

    func uploadFile()  {

        let fileURL = Bundle.main.url(forResource:"video", withExtension:"mov")

 

        Alamofire.upload(fileURL!, to: url).responseJSON { response in

            debugPrint(response)

        }

    }

 

 //uploadMultiFormData----上传多个表单数据

    func uploadMultiFormData()  {

        Alamofire.upload(

            multipartFormData: { multipartFormData in//添加多个表单数据是吧本地url传上去

//                multipartFormData.append(unicornImageURL, withName: "unicorn")

//                multipartFormData.append(rainbowImageURL, withName: "rainbow")

        },

            to: url,

            encodingCompletion: { encodingResult in

                switch encodingResult {

                case .success(let upload,_,_):

                    upload.responseJSON { responsein

                        debugPrint(response)

                    }

                case .failure(let encodingError):

                    print(encodingError)

                }

        }

        )

    }

    

    

 //上传带进度条

    func uploadWithProgress() {

        let fileURL = Bundle.main.url(forResource:"video", withExtension:"mov")

        

        Alamofire.upload(fileURL!, to: url)

            .uploadProgress { progress in // main queue by default

                print("Upload Progress:\(progress.fractionCompleted)")

            }

            .downloadProgress { progress in // main queue by default

                print("Download Progress:\(progress.fractionCompleted)")

            }

            .responseJSON { response in

                debugPrint(response)

        }

    }

 

上传下载参考:https://www.jianshu.com/p/f8c3adb056cf

下载参考:http://www.hangge.com/blog/cache/detail_972.html

=============创建sessionManager和设置Configuration

 

Session Manager

 

高级别的方便的方法,例如Alamofire.request,使用的是默认的Alamofire.SessionManager,并且这个SessionManager是用默认URLSessionConfiguration配置的。

 

例如,下面两个语句是等价的:

 

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

 

***let sessionManager = Alamofire.SessionManager.default

sessionManager.request("https://xx.com")

我们可以自己创建后台会话和短暂会话的session manager,还可以自定义默认的会话配置来创建新的session manager,例如修改默认的header httpAdditionalHeaders和timeoutIntervalForRequest。

 

 方式一:

let configuration =URLSessionConfiguration.default

let sessionManager = Alamofire.SessionManager(configuration: configuration)

 

方式二:

let configuration = URLSessionConfiguration.background(withIdentifier:"com.example.app.background")

let sessionManager = Alamofire.SessionManager(configuration: configuration)

 

方式三:

let configuration =URLSessionConfiguration.ephemeral

let sessionManager = Alamofire.SessionManager(configuration: configuration)

 

更改configration:

var defaultHeaders = Alamofire.SessionManager.defaultHTTPHeaders

defaultHeaders["DNT"] ="1 (Do Not Track Enabled)"

 

let configuration =URLSessionConfiguration.default

configuration.httpAdditionalHeaders =defaultHeaders

 

let sessionManager = Alamofire.SessionManager(configuration:configuration)

 

 

 

=============序列化=解析数据====================================

1.**********************IOS系统的序列化器,吧JSON字符串解析成JSON对象(字典)

  //1.这是一个JSON字符串

        let jsonStr ="[{\"name\": \"hangge\", \"age\": 100, \"phones\": [{\"name\": \"公司\",\"number\": \"123456\"}, {\"name\": \"家庭\",\"number\": \"001\"}]}, {\"name\": \"big boss\",\"age\": 1,\"phones\": [{ \"name\": \"公司\",\"number\": \"111111\"}]}]"

        

        //2.吧JSON字符串变成data数据

        if let jsonData = jsonStr.data(using:String.Encoding.utf8, allowLossyConversion:false) {

            

            do{

        //3.吧jsondata转换成JSON对象(即字典,或字典数组)

            if  let dictArr:[[String:Any]]=(tryJSONSerialization.jsonObject(with:jsonData,options:.allowFragments)as?[[String :Any]])  {

                    let phones = dictArr[0]["phones"]as?[[String:Any]]

                    if let name = phones![0]["name"]as?String{

                         print("\(name)")

                    }

                }

            }

            catch{

                

            }

        }

        

=================SwiftJson是Swift 界 JSON 解析之王(不是字典转模型)=============

 

下载地址:https://github.com/SwiftyJSON/SwiftyJSON

 

coacaopods导入SwiftJson框架;

在工程中导入第三方的头文件时,会报以下的错误:cannot load underlying module for ‘***’

这个问题出现的原因还是因为podfile文件,你需要在文件里再加上一句话  source 'https://github.com/CocoaPods/Specs.git'

如果还是这样,需要在LinkFrameworkAndLibrary中加入SwiftFramework.frame work

 

 

2.//**************swiftyjson吧JSON字符串解析成JSON对象(字典)******************不用担心数组越界,不用判断节点,拆包什么的

            do{

                let json = try JSON(data: jsonData, options:.allowFragments)

                if let number = json[0]["phones"][0]["number"].string {

                    // 找到电话号码

                    print("第一个联系人的第一个电话号码:",number)

                }else {

                    // 打印错误信息

                    print(json[0]["phones"][0]["number"])

                }

            }catch{

                

            }

=================================================================           

=======================Alamofire中sessionManager的使用=============

===========请求获取数据=====

LYBHomeHttp类中:

 

    static var sessionManager:SessionManager? = nil//这里的自定义sessionManager必须被强引用,否则不起作用

   

//============//static修饰的属性只能用类调用,

    func sessionM(){

        let  config=URLSessionConfiguration.default

        config.timeoutIntervalForRequest=30//超时时间

        config.httpMaximumConnectionsPerHost=2//最大连接数

        let defaultHeaderss = Alamofire.SessionManager.defaultHTTPHeaders

//        defaultHeaderss["DNT"] = "1 (Do Not Track Enabled)"

        config.httpAdditionalHeaders = defaultHeaderss

        LYBHomeHttp.sessionManager=Alamofire.SessionManager(configuration: config)

        LYBHomeHttp.sessionManager?.request(url, method: .get, parameters: nil, encoding:URLEncoding.default, headers: defaultHeaderss).responseJSON { (response) in

            print(response)//请求到的全部数据--控制台打印SUCCESS:{}

            

            print(response.result)//控制台打印出SUCCESS或者FAILURE

            

            switch response.result{

            case .success(let value):

                print(value)//控制台打印出SUCCESS对应的数据{请求到的后台数据}

            case .failure(let error):

                print(error)//控制台打印出FAILURE对应的错误信息{返回的错误信息}

            }

            

        }

    }

 

=============请求code=-999报错的解决:https://www.jianshu.com/p/e62d87b2e174======

解决:  static var sessionManager:SessionManager? = nil//这里的自定义sessionManager必须被强引用,否则不起作用

 

=======sessionManager上传=====sessionManager下载======

/**
 网络下载,暂停下载,继续接着上一次下载,上传数据
 */

import UIKit

class LYBDownAndUpLoadHttpManager: NSObject {
    static var manager:SessionManager? = nil//这里的sessionManager需要被强引用,否则不起作用
    var cancelledData:Data?//已下载的数据临时存储起来
    let serviceAddresss="http://";//上传到服务器资源地址--上传
    let downloadUrl="http://"//服务器的资源地址--下载
    var downrequest:Request?=nil//下载的请求
    var uprequest:Request? = nil//上传的请求
    
    func createManage(){
        
        let  config=URLSessionConfiguration.default
        config.timeoutIntervalForRequest=30//超时时间
        config.httpMaximumConnectionsPerHost=2//最大连接数
        var defaultHeaderss = Alamofire.SessionManager.defaultHTTPHeaders
        defaultHeaderss.updateValue("application/json", forKey: "Accept")
        config.httpAdditionalHeaders = defaultHeaderss
        
        //根据config创建manager-----不验证域名
        LYBDownAndUpLoadHttpManager.manager=SessionManager(configuration: config)
    }
   
        
   
        //指定下载路径(文件名不变)-这是一个闭包
        let destination: DownloadRequest.DownloadFileDestination = {
            _, response in
            
            let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
            let fileURL = documentsURL.appendingPathComponent(response.suggestedFilename!)//response.suggestedFilename!是系统推荐的路径,也可以自己定义路径:"file/mypath.png"
            //两个参数表示如果有同名文件则会覆盖,如果路径中文件夹不存在则会自动创建
            return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
        }
    
    
    /**
     创建下载请求,
     parama1:url 服务器的下载地址
     parama2:destination 本地存储的地址
     */
   
    func createDownloadRequest(downloadUrl: String,success: @escaping success,
        failure: @escaping failure){
        createManage()
        downrequest = ( LYBDownAndUpLoadHttpManager.manager!.download(URLRequest.init(url:URL.init(string: downloadUrl)!), to: destination).responseJSON(completionHandler: { (response) in
            print(response.result)
            switch response.result {
            case .success( _):
                success(response as AnyObject)
            case .failure:
                self.cancelledData = response.resumeData //意外终止的话,把已下载的数据储存起来
                failure(response as AnyObject)
            }
        }))
        
    }
    
    func cancelDownload(){
        downrequest?.cancel()//暂停下载
    }
    
    
    
        /**
         继续下载
         parama1:cancelledDatay上次下载的数数据
         parama2:destination 本地存储的地址
         */
    func continueDownLoad(success: @escaping success,
                          failure: @escaping failure){
        createManage()
        LYBDownAndUpLoadHttpManager.manager!.download(resumingWith: self.cancelledData!, to: destination).responseJSON(completionHandler: { (response) in
            print(response.result)
            switch response.result {
            case .success( _):
                //self.image = UIImage(data: data)
                success(response as AnyObject)
            case .failure:
                self.cancelledData = response.resumeData //意外终止的话,把已下载的数据储存起来
                failure(response as AnyObject)
        }
        })
       
    }
    
//=================================================
    /**
      上传data数据到服务器
     */
    public func uploadWithData(url: String,
                                data: Data,
                                success: @escaping success,
                                failure: @escaping failure){
        createManage()
        let data:Data=UIImage.init(named: "bannerhomeOne")!.pngData()!
        uprequest  =  ( LYBDownAndUpLoadHttpManager.manager!.upload(data, to: serviceAddresss, method: .post, headers: nil).responseJSON(completionHandler: { (response) in
            switch response.result {
            case .success( _):
                
                print("文件下载完毕: \(response)")
            case .failure(let error):
                print(error)
            }
        }))
    }
    
    
    func cancelUpload(){
        uprequest?.cancel()//取消
    
    }
    
    
    /**
      吧本地路径的资源上传到服务器
     parama1:服务器地址
     parama2:本地路径
     */
    public func uploadWithLocalpath(url: String,
                              path: String,
                              success: @escaping success,
                              failure: @escaping failure){
        createManage()
        let   path=NSHomeDirectory() + "file"
        LYBDownAndUpLoadHttpManager.manager!.upload(URL.init(string: path)!, to: serviceAddresss).responseJSON(completionHandler: { (response) in
            switch response.result {
            case .success( _):
                
                print("文件上传完毕: \(response)")
            case .failure(let error):
                print(error)
            }
        })
    }
    
}

=================设置httpheder=========


//*********在iOS7中要中以下方法才有效

private func getRequest(method: Method, _ URLString: URLStringConvertible, parameters: [String: AnyObject]? = nil) -> NSMutableURLRequest {
        let request = NSMutableURLRequest(URL: NSURL(string: URLString.URLString)!)
        request.HTTPMethod = method.rawValue
        if parameters != nil {
            request.HTTPBody = NSJSONSerialization.dataWithJSONObject(parameters!, options: nil, error: nil)
        }
        request.setValue(API_UA, forHTTPHeaderField: "User-Agent")
        request.setValue(HEADER_ACCEPT, forHTTPHeaderField: "Accept")
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        
        return request
    }




//************iOS8中的社会httpheader要用httpAdditionalHeaders

  //创建httpHeader
        var defaultHeaders = Alamofire.SessionManager.defaultHTTPHeaders
        //给httpheader添加内容
        defaultHeaders["token"] = "token的内容"
        defaultHeaders["Authorization"] = ""
        defaultHeaders.updateValue("application/json", forKey: "Accept")
        config.httpAdditionalHeaders = defaultHeaders //     config.httpAdditionalHeaders=[:]//http请求头,或者直接这样写

===========全局请求头和局部请求头==========

.*******局部请求头*********
客户端每发起一次HTTP请求,请求头信息是必不可少的。这也是同服务器交流的一种手段,在实际的开发中,也肯定会遇到需要自定义请求头的需求,在Alamofire中如何设置请求头:
let headers: HTTPHeaders = [
    "Authorization": "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==",
    "Accept": "application/json"
]

Alamofire.request("https://httpbin.org/headers", headers: headers).responseJSON { response in
    debugPrint(response)
}

在request(...)函数中,存在headers这么一个参数,我们只要传入提前写好的字典就行了。

********全局请求头*********
使用URLSessionConfiguration来配置全局的属性,
需要说明的是,Alamofire为每一个请求都设置了默认的请求头,我们简单介绍一下:
(1)Accept-Encoding 表示可接受的编码方式,值为:gzip;q=1.0, compress;q=0.5
(2)Accept-Language 表示可接受的语言,这个在后边的文章中会详细说明
(3)User-Agent 表示用户代理信息,比如:iOS Example/1.0 (com.alamofire.iOS-Example; build:1; iOS 10.0.0) Alamofire/4.0.0

默认的请求头配置,我们通过SessionManager.default来创建SessionManager:
open static let `default`: SessionManager = {
        let configuration = URLSessionConfiguration.default
        configuration.httpAdditionalHeaders = SessionManager.defaultHTTPHeaders

        return SessionManager(configuration: configuration)
    }()

 

你可能感兴趣的:(iOS,/swift)