美文网首页
swift 动手写网络请求封装(仿照了一个大神的)不用导入第三方

swift 动手写网络请求封装(仿照了一个大神的)不用导入第三方

作者: 762683ff5d3d | 来源:发表于2017-08-14 11:20 被阅读0次

    新建一个类Network

    importUIKit

    //NSURLSession的使用过程:

    //

    //构造NSURLRequest

    //确定URL

    //确定HTTP方法(GET、POST等)

    //添加特定的HTTP头

    //填充HTTP Body

    //驱动session.dataTaskWithRequest方法,开始请求

    //(5)设置SSL证书钢钉。在我们调用HTTPS协议的时候,事先把SSL证书存到App本地,然后在每次请求的时候都进行一次验证,避免中间人攻击(Man-in-the-middle attack)。同时,这个功能也是我们使用自签名证书时候必须的,因为系统默认会拒绝我们自己签名的不受信任的证书,导致连接失败。

    // MARK:提供的各种调用接口:GET,POST,文件上传

    classNetwork:NSObject{

    //不带参数的get请求

    /*

    请求方法的URL    url: get

    callback闭包[data:请求成功的数据,

    response:拿到数据的解析回应,

    error:请求错误]

    NetworkManager()一个初始化URL、params、http、files文件的类

    fire()使用一个统一的方法来驱动上面三个function(),完成请求:

    */

    staticfuncget(url:String, callback: (data:NSData!, response:NSURLResponse!, error:NSError!) ->Void) {

    letmanager =NetworkManager(url: url, method:"GET", callback: callback)

    manager.fire()

    }

    //带参数的get请求

    /*

    请求方法的URL    url: get

    请求参数params:dictionary

    callback闭包[data:请求成功的数据,

    response:拿到数据的解析回应,

    error:请求错误]

    NetworkManager()一个初始化URL、params、http、files文件的类

    fire()使用一个统一的方法来驱动上面三个function(),完成请求:

    */

    staticfuncget(url:String, params:Dictionary, callback: (data:NSData!, response:NSURLResponse!, error:NSError!) ->Void) {

    letmanager =NetworkManager(url: url, method:"GET", params: params, callback: callback)

    manager.fire()

    }

    //不带参数的post请求

    /*

    请求方法的URL    url: post

    callback闭包[data:请求成功的数据,

    response:拿到数据的解析回应,

    error:请求错误]

    NetworkManager()一个初始化URL、params、http、files文件的类

    fire()使用一个统一的方法来驱动上面三个function(),完成请求:

    */

    staticfuncpost(url:String, callback: (data:NSData!, response:NSURLResponse!, error:NSError!) ->Void) {

    letmanager =NetworkManager(url: url, method:"POST", callback: callback)

    manager.fire()

    }

    //带参数的post请求

    /*

    请求方法的URL    url: post

    请求参数params:dictionary

    callback闭包[data:请求成功的数据,

    response:拿到数据的解析回应,

    error:请求错误]

    NetworkManager()一个初始化URL、params、http、files文件的类

    fire()使用一个统一的方法来驱动上面三个function(),完成请求:

    */

    staticfuncpost(url:String, params:Dictionary, callback: (data:NSData!, response:NSURLResponse!, error:NSError!) ->Void) {

    letmanager =NetworkManager(url: url, method:"POST", params: params, callback: callback)

    manager.fire()

    }

    //MARK:不带params和files的接口

    /*

    提供请求方法类型method: String

    请求方法的URL    url: String

    callback闭包[data:请求成功的数据,

    response:拿到数据的解析回应,

    error:请求错误]

    NetworkManager()一个初始化URL、params、http、files文件的类

    fire()使用一个统一的方法来驱动上面三个function(),完成请求:

    */

    staticfuncrequest(method:String, url:String, callback: (data:NSData!, response:NSURLResponse!, error:NSError!) ->Void) {

    letmanager =NetworkManager(url: url, method: method, callback: callback)

    manager.fire()

    }

    //MARK:带参数不带files

    /*

    提供请求方法类型method: String

    请求方法的URL    url: String

    请求方法的参数params: Dictionary

    callback闭包[data:请求成功的数据,

    response:拿到数据的解析回应,

    error:请求错误]

    NetworkManager()一个初始化URL、params、http、files文件的类

    fire()使用一个统一的方法来驱动上面三个function(),完成请求:

    */

    staticfuncrequest(method:String, url:String, params:Dictionary, callback: (data:NSData!, response:NSURLResponse!, error:NSError!) ->Void) {

    letmanager =NetworkManager(url: url, method: method, params: params, callback: callback)

    manager.fire()

    }

    //MARK:不带参数带files

    /*

    提供请求方法类型method: String

    请求方法的URL    url: String

    请求文件files:array

    callback闭包[data:请求成功的数据,

    response:拿到数据的解析回应,

    error:请求错误]

    NetworkManager()一个初始化URL、params、http、files文件的类

    fire()使用一个统一的方法来驱动上面三个function(),完成请求:

    */

    staticfuncrequest(method:String, url:String, files:Array, callback: (data:NSData!, response:NSURLResponse!, error:NSError!) ->Void) {

    letmanager =NetworkManager(url: url, method: method, files: files, callback: callback)

    manager.fire()

    }

    //MARK:带参数和files的接口

    /*

    提供请求方法类型method: String

    请求方法的URL    url: String

    请求方法的参数params: Dictionary

    请求文件files:array

    callback闭包[data:请求成功的数据,

    response:拿到数据的解析回应,

    error:请求错误]

    NetworkManager()一个初始化URL、params、http、files文件的类

    fire()使用一个统一的方法来驱动上面三个function(),完成请求:

    */

    staticfuncrequest(method:String, url:String, params:Dictionary, files:Array, callback: (data:NSData!, response:NSURLResponse!, error:NSError!) ->Void) {

    letmanager =NetworkManager(url: url, method: method, params: params, files: files, callback: callback)

    manager.fire()

    }

    }

    // MARK: - nsdata属性是string的扩展

    extensionString{

    varnsdata:NSData{

    returnself.dataUsingEncoding(NSUTF8StringEncoding)!

    }

    }

    // MARK:定义的文件格式

    structFile {

    letname:String!

    leturl:NSURL!

    init(name:String, url:NSURL) {

    self.name= name

    self.url= url

    }

    }

    // MARK: -新建一个NetworkManager类,将URL、params、files等设为成员变量,让他们在构造函数中初始化:

    classNetworkManager:NSObject,NSURLSessionDelegate{//证书实现NSURLSessionDelegate的协议

    //todo  boundary是我们自己指定的文件间隔符。

    letboundary ="PitayaUGl0YXlh"

    letmethod:String!

    letparams:Dictionary

    letcallback: (data:NSData!, response:NSURLResponse!, error:NSError!) ->Void

    // add files

    varfiles:Array

    varsession:NSURLSession!

    leturl:String!

    varrequest:NSMutableURLRequest!

    vartask:NSURLSessionTask!

    //ssl增加两个成员变量实现ssl证书检查代理方法干预网络请求

    varlocalCertData:NSData!

    varsSLValidateErrorCallBack: (() ->Void)?

    // add files

    init(url:String, method:String, params:Dictionary =Dictionary(), files:Array =Array(), callback: (data:NSData!, response:NSURLResponse!, error:NSError!) ->Void) {

    self.url= url

    self.request=NSMutableURLRequest(URL:NSURL(string: url)!)

    self.method= method

    self.params= params

    self.callback= callback

    // add files

    self.files= files

    super.init()

    //ssl自定义nsurlsession对象

    self.session=NSURLSession(configuration:NSURLSession.sharedSession().configuration, delegate:self, delegateQueue:NSURLSession.sharedSession().delegateQueue)

    }

    //ssl增加设置ssl函数

    funcaddSSLPinning(LocalCertData data:NSData, SSLValidateErrorCallBack: (()->Void)? =nil) {

    self.localCertData= data

    self.sSLValidateErrorCallBack= SSLValidateErrorCallBack

    }

    //ssl实现证书代理方法,介入网络请求

    @objcfuncURLSession(session:NSURLSession, didReceiveChallenge challenge:NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition,NSURLCredential?) ->Void) {

    ifletlocalCertificateData =self.localCertData{

    ifletserverTrust = challenge.protectionSpace.serverTrust,

    certificate =SecTrustGetCertificateAtIndex(serverTrust,0),

    remoteCertificateData:NSData=SecCertificateCopyData(certificate) {

    iflocalCertificateData.isEqualToData(remoteCertificateData) {

    letcredential =NSURLCredential(forTrust: serverTrust)

    challenge.sender?.useCredential(credential, forAuthenticationChallenge: challenge)

    completionHandler(NSURLSessionAuthChallengeDisposition.UseCredential, credential)

    }else{

    challenge.sender?.cancelAuthenticationChallenge(challenge)

    completionHandler(NSURLSessionAuthChallengeDisposition.CancelAuthenticationChallenge,nil)

    self.sSLValidateErrorCallBack?()

    }

    }else{

    NSLog("Get RemoteCertificateData or LocalCertificateData error!")

    }

    }else{

    completionHandler(NSURLSessionAuthChallengeDisposition.UseCredential,nil)

    }

    }

    //MARK:使用一个统一的方法来驱动上面三个function,完成请求:

    funcfire() {

    buildRequest()

    buildBody()

    fireTask()

    }

    //MARK:确定URL、http方法、添加特定的http头

    funcbuildRequest() {

    ifself.method=="GET"&&self.params.count>0{

    self.request=NSMutableURLRequest(URL:NSURL(string:url+"?"+buildParams(self.params))!)

    }

    request.HTTPMethod=self.method

    //   Content-Type

    ifself.files.count>0{

    request.addValue("multipart/form-data; boundary="+self.boundary, forHTTPHeaderField:"Content-Type")

    }elseifself.params.count>0{

    request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField:"Content-Type")

    }

    }

    //MARK:填充HTTP Body

    funcbuildBody() {

    letdata =NSMutableData()

    ifself.files.count>0{

    ifself.method=="GET"{

    NSLog("\n\n------------------------\nThe remote server may not accept GET method with HTTP body. But Pitaya will send it anyway.\n------------------------\n\n")

    }

    for(key, value)inself.params{

    data.appendData("--\(self.boundary)\r\n".nsdata)

    data.appendData("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n".nsdata)

    data.appendData("\(value.description)\r\n".nsdata)

    }

    forfileinself.files{

    data.appendData("--\(self.boundary)\r\n".nsdata)

    data.appendData("Content-Disposition: form-data; name=\"\(file.name)\"; filename=\"\(NSString(string: file.url.description).lastPathComponent)\"\r\n\r\n".nsdata)

    ifleta =NSData(contentsOfURL: file.url) {

    data.appendData(a)

    data.appendData("\r\n".nsdata)

    }

    }

    data.appendData("--\(self.boundary)--\r\n".nsdata)

    }elseifself.params.count>0&&self.method!="GET"{

    data.appendData(buildParams(self.params).nsdata)

    }

    request.HTTPBody= data

    }

    //MARK:将请求任务执行

    funcfireTask() {

    task=session.dataTaskWithRequest(request, completionHandler: { (data, response, error) ->Voidin

    self.callback(data: data, response: response, error: error)

    })

    task.resume()

    }

    // MARK:从Alamofire偷了三个函数

    funcbuildParams(parameters: [String:AnyObject]) ->String{

    varcomponents: [(String,String)] = []

    forkeyinArray(parameters.keys).sort(<) {

    letvalue:AnyObject! = parameters[key]

    components +=self.queryComponents(key, value)

    }

    return(components.map{"\($0)=\($1)"}as[String]).joinWithSeparator("&")

    }

    funcqueryComponents(key:String,_value:AnyObject) -> [(String,String)] {

    varcomponents: [(String,String)] = []

    ifletdictionary = valueas? [String:AnyObject] {

    for(nestedKey, value)indictionary {

    components +=queryComponents("\(key)[\(nestedKey)]", value)

    }

    }elseifletarray = valueas? [AnyObject] {

    forvalueinarray {

    components +=queryComponents("\(key)", value)

    }

    }else{

    components.appendContentsOf([(escape(key),escape("\(value)"))])

    }

    returncomponents

    }

    funcescape(string:String) ->String{

    letlegalURLCharactersToBeEscaped:CFStringRef=":&=;+!@#$()',*"

    returnCFURLCreateStringByAddingPercentEscapes(nil, string,nil, legalURLCharactersToBeEscaped,CFStringBuiltInEncodings.UTF8.rawValue)asString

    }

    }

    主界面测试:

    importUIKit

    classViewController:UIViewController{

    overridefuncviewDidLoad() {

    super.viewDidLoad()

    // Do any additional setup after loading the view, typically from a nib.

    letmainBtn =UIButton.init(frame:CGRectMake(200,200,100,50))

    mainBtn.backgroundColor=UIColor.redColor()

    mainBtn.addTarget(self, action:#selector(mainBtnBeTapped), forControlEvents: .TouchUpInside)

    self.view.addSubview(mainBtn)

    }

    funcmainBtnBeTapped(sender:AnyObject) {

    leturl ="http://pitayaswift.sinaapp.com/pitaya.php"

    Network.post(url, callback: { (data, response, error) ->Voidin

    print("POST 1请求成功")

    })

    Network.post(url, params: ["post":"POST Network"], callback: { (data, response, error) ->Voidin

    letstring =NSString(data: data, encoding:NSUTF8StringEncoding)as!String

    print("POST 2请求成功"+ string)

    })

    Network.get(url, callback: { (data, response, error) ->Voidin

    print("GET 1请求成功")

    })

    Network.get(url, params: ["get":"POST Network"], callback: { (data, response, error) ->Voidin

    letstring =NSString(data: data, encoding:NSUTF8StringEncoding)as!String

    print("GET 2请求成功"+ string)

    })

    Network.request("GET", url: url, params: ["get":"Request Network"]) { (data, response, error) ->Voidin

    letstring =NSString(data: data, encoding:NSUTF8StringEncoding)as!String

    print("Request请求成功"+ string)

    }

    }

    }

    来一张测试图:

    May there be enough clouds in your life to make a beautiful sunset...

    原文: http://www.cnblogs.com/linxiu-0925/p/5761040.html
    这篇文章写的还不错觉得还可以再提炼一下,后期有时间也会发布自己封装的

    相关文章

      网友评论

          本文标题:swift 动手写网络请求封装(仿照了一个大神的)不用导入第三方

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