新建一个类Network

import UIKit

//NSURLSession 的使用过程:

//

//构造 NSURLRequest

//确定 URL

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

//添加特定的 HTTP 头

//填充 HTTP Body

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

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

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

class Network: NSObject{

// 不带参数的get请求

/*

请求方法的URL    url: get

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

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

error: 请求错误]

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

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

*/

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

let manager = 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(),完成请求:

*/

static func get(url: String, params: Dictionary<String, AnyObject>, callback: (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void) {

let manager = 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(),完成请求:

*/

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

let manager = 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(),完成请求:

*/

static func post(url: String, params: Dictionary<String, AnyObject>, callback: (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void) {

let manager = 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(),完成请求:

*/

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

let manager = 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(),完成请求:

*/

static func request(method: String, url: String, params: Dictionary<String, AnyObject>, callback: (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void) {

let manager = 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(),完成请求:

*/

static func request(method: String, url: String, files: Array<File>, callback: (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void) {

let manager = 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(),完成请求:

*/

static func request(method: String, url: String, params: Dictionary<String, AnyObject>, files: Array<File>, callback: (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void) {

let manager = NetworkManager(url: url, method: method, params: params, files: files, callback: callback)

manager.fire()

}

}

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

extension String {

var nsdata: NSData {

return self.dataUsingEncoding(NSUTF8StringEncoding)!

}

}

// MARK: 定义的文件格式

struct File {

let name: String!

let url: NSURL!

init(name: String, url: NSURL) {

self.name = name

self.url = url

}

}

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

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

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

let boundary = "PitayaUGl0YXlh"

let method: String!

let params: Dictionary<String, AnyObject>

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

// add files

var files: Array<File>

var session: NSURLSession!

let url: String!

var request: NSMutableURLRequest!

var task: NSURLSessionTask!

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

var localCertData: NSData!

var sSLValidateErrorCallBack: (() -> Void)?

// add files

init(url: String, method: String, params: Dictionary<String, AnyObject> = Dictionary<String, AnyObject>(), files: Array<File> = Array<File>(), 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函数

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

self.localCertData = data

self.sSLValidateErrorCallBack = SSLValidateErrorCallBack

}

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

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

if let localCertificateData = self.localCertData {

if let serverTrust = challenge.protectionSpace.serverTrust,

certificate = SecTrustGetCertificateAtIndex(serverTrust, 0),

remoteCertificateData: NSData = SecCertificateCopyData(certificate) {

if localCertificateData.isEqualToData(remoteCertificateData) {

let credential = 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,完成请求:

func fire() {

buildRequest()

buildBody()

fireTask()

}

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

func buildRequest() {

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

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

}

request.HTTPMethod = self.method

//   Content-Type

if self.files.count > 0 {

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

} else if self.params.count > 0 {

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

}

}

//MARK:  填充 HTTP Body

func buildBody() {

let data = NSMutableData()

if self.files.count > 0 {

if self.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) in self.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)

}

for file in self.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)

if let a = NSData(contentsOfURL: file.url) {

data.appendData(a)

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

}

}

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

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

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

}

request.HTTPBody = data

}

//MARK:  将请求任务执行

func fireTask() {

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

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

})

task.resume()

}

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

func buildParams(parameters: [String: AnyObject]) -> String {

var components: [(String, String)] = []

for key in Array(parameters.keys).sort(<) {

let value: AnyObject! = parameters[key]

components += self.queryComponents(key, value)

}

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

}

func queryComponents(key: String, _ value: AnyObject) -> [(String, String)] {

var components: [(String, String)] = []

if let dictionary = value as? [String: AnyObject] {

for (nestedKey, value) in dictionary {

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

}

} else if let array = value as? [AnyObject] {

for value in array {

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

}

} else {

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

}

return components

}

func escape(string: String) -> String {

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

return CFURLCreateStringByAddingPercentEscapes(nil, string, nil, legalURLCharactersToBeEscaped, CFStringBuiltInEncodings.UTF8.rawValue) as String

}

}

主界面测试:

import UIKit

class ViewController: UIViewController {

override func viewDidLoad() {

super.viewDidLoad()

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

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

mainBtn.backgroundColor = UIColor.redColor()

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

self.view.addSubview(mainBtn)

}

func mainBtnBeTapped(sender:AnyObject) {

let url = "http://pitayaswift.sinaapp.com/pitaya.php"

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

print("POST 1 请求成功")

})

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

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

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

})

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

print("GET 1 请求成功")

})

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

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

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

})

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

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

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

}

}

}

来一张测试图:

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

  1. 十. Axios网络请求封装

    1. 网络模块的选择 Vue中发送网络请求有非常多的方式,那么在开发中如何选择呢? 选择一:传统的Ajax是基于XMLHttpRequest(XHR) 为什么不用它呢?非常好解释配置和调用方式等非常混 ...

  2. React-Native 之 GD (八)GET 网络请求封装

    1.到这里,相信各位对 React-Native 有所熟悉了吧,从现在开始我们要慢慢往实际的方向走,这边就先从网络请求这部分开始,在正式开发中,网络请求一般都单独作为一部分,我们在需要使用的地方只需要 ...

  3. flutter dio网络请求封装实现

    flutter dio网络请求封装实现 文章友情链接:   https://juejin.im/post/6844904098643312648 在Flutter项目中使用网络请求的方式大致可分为两种 ...

  4. iOS开发--Swift 基于AFNetworking 3.0的网络请求封装

    Swift和OC基于AFNetworking的网络请求流程相同, 就是语法不同, 对于Swift语法不是很清楚的同学, 建议多看看API文档, 自己多多尝试. 写过OC的应该都明白每句话做什么的, 就 ...

  5. 【Swift】Alamofile网络请求数据更新TableView的坑

    写这篇BLOG前,有些话不得不提一下,就仅当发发恼骚吧... 今天下午为了一个Alamofire取得数据而更新TableView的问题,查了一下午的百度(360也是见鬼的一样),竟然没有一个简单明了的 ...

  6. Android项目开发全程(三)-- 项目的前期搭建、网络请求封装是怎样实现的

    在前两篇博文中已经做了铺垫,下面咱们就可以用前面介绍过的内容开始做一个小项目了(项目中会用到Afinal框架,不会用Afinal的童鞋可以先看一下上一篇博文),正所谓麻雀虽小,五脏俱全,这在里我会尽量 ...

  7. React Native 网络请求封装:使用Promise封装fetch请求

    最近公司使用React作为前端框架,使用了异步请求访问,这里做下总结: React Native中虽然也内置了XMLHttpRequest 网络请求API(也就是俗称的ajax),但XMLHttpRe ...

  8. Android,适合Restful网络请求封装

    借助volley.Gson类库. 优点 网络请求集中处理,返回值直接为预期的对象,不需要手动反序列,提高效率,使用时建立好model类即可. 使用效果 DataProess.Request(true, ...

  9. iOS开发——post异步网络请求封装

    IOS中有许多网络请求的函数,同步的,异步的,通过delegate异步回调的. 在做一个项目的时候,上网看了很多别人的例子,发现都没有一个简单的,方便的异步请求的封装例子.我这里要给出的封装代码,是异 ...

随机推荐

  1. js:插入节点appendChild insertBefore使用方法

    首先 从定义来理解 这两个方法: appendChild() 方法:可向节点的子节点列表的末尾添加新的子节点.语法:appendChild(newchild) insertBefore() 方法:可在 ...

  2. 项目管理学习笔记之五.沟通协调能力I

    项目管理个人能力培养--沟通协调能力在项目管理当中,怎么样把握好沟通?它有些什么的基本原则?是我们本章要讨论的. 一.电影<大腕>中的四段对话 冯小刚的电影<大腕>中有四段精神 ...

  3. Linux老是提示compat-libstdc++ is not installed的原因

    在一Linux服务器上检查是否安装了一些包时,遇到老是提示"package compat-libstdc++ is not installed" [root@DB-Server ~ ...

  4. SQLServer基本函数

    1.字符串函数  长度与分析用 datalength(Char_expr) 返回字符串包含字符数,但不包含后面的空格 substring(expression,start,length) 取子串 ri ...

  5. MySql安装与MySQL添加用户、删除用户与授权

    1.安装MySql       目前MySQL有两种形式的文件,一个是msi格式,一个是zip格式的.msi格式的直接点击setup.exe就好,按照步骤进行.但是很多人下了zip格式的解压发现没有s ...

  6. 【Linux】将Oracle安装目录从根目录下迁移到逻辑卷

    [Linux]将Oracle安装目录从根目录下迁移到逻辑卷 1.1  BLOG文档结构图 1.2  前言部分 1.2.1  导读和注意事项 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到 ...

  7. python基础(四)运算

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! Python的运算符和其他语言类似 (我们暂时只了解这些运算符的基本用法,方便我们 ...

  8. 成为 Linux 终端高手的七种武器 之七 条件执行&&

    7.条件执行 Bash 也可以连续执行两条命令。 第二条命令仅在第一条命令成功执行后才会开始执行。如要如此,你可以通过键入“&&”,也就是两个“&”字符进行分隔,在同一行输入两 ...

  9. Javascript字数统计

    字数统计功能,原理是给textarea添加onKeyup事件,事件读取textarea内容并获得长度,并赋值给统计字数的那个文本节点,这里有一点要注意的是添加onKeypress和onKeydown事 ...

  10. elasticsearch 集群搭建

    需要编辑的文件是config/elasticsearch.yml文件 需要配置的项目有: # Use a descriptive name for your cluster: # cluster.na ...