swift 动手写网络请求封装(仿照了一个大神的)不用导入第三方
新建一个类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 动手写网络请求封装(仿照了一个大神的)不用导入第三方的更多相关文章
- 十. Axios网络请求封装
1. 网络模块的选择 Vue中发送网络请求有非常多的方式,那么在开发中如何选择呢? 选择一:传统的Ajax是基于XMLHttpRequest(XHR) 为什么不用它呢?非常好解释配置和调用方式等非常混 ...
- React-Native 之 GD (八)GET 网络请求封装
1.到这里,相信各位对 React-Native 有所熟悉了吧,从现在开始我们要慢慢往实际的方向走,这边就先从网络请求这部分开始,在正式开发中,网络请求一般都单独作为一部分,我们在需要使用的地方只需要 ...
- flutter dio网络请求封装实现
flutter dio网络请求封装实现 文章友情链接: https://juejin.im/post/6844904098643312648 在Flutter项目中使用网络请求的方式大致可分为两种 ...
- iOS开发--Swift 基于AFNetworking 3.0的网络请求封装
Swift和OC基于AFNetworking的网络请求流程相同, 就是语法不同, 对于Swift语法不是很清楚的同学, 建议多看看API文档, 自己多多尝试. 写过OC的应该都明白每句话做什么的, 就 ...
- 【Swift】Alamofile网络请求数据更新TableView的坑
写这篇BLOG前,有些话不得不提一下,就仅当发发恼骚吧... 今天下午为了一个Alamofire取得数据而更新TableView的问题,查了一下午的百度(360也是见鬼的一样),竟然没有一个简单明了的 ...
- Android项目开发全程(三)-- 项目的前期搭建、网络请求封装是怎样实现的
在前两篇博文中已经做了铺垫,下面咱们就可以用前面介绍过的内容开始做一个小项目了(项目中会用到Afinal框架,不会用Afinal的童鞋可以先看一下上一篇博文),正所谓麻雀虽小,五脏俱全,这在里我会尽量 ...
- React Native 网络请求封装:使用Promise封装fetch请求
最近公司使用React作为前端框架,使用了异步请求访问,这里做下总结: React Native中虽然也内置了XMLHttpRequest 网络请求API(也就是俗称的ajax),但XMLHttpRe ...
- Android,适合Restful网络请求封装
借助volley.Gson类库. 优点 网络请求集中处理,返回值直接为预期的对象,不需要手动反序列,提高效率,使用时建立好model类即可. 使用效果 DataProess.Request(true, ...
- iOS开发——post异步网络请求封装
IOS中有许多网络请求的函数,同步的,异步的,通过delegate异步回调的. 在做一个项目的时候,上网看了很多别人的例子,发现都没有一个简单的,方便的异步请求的封装例子.我这里要给出的封装代码,是异 ...
随机推荐
- Java Maps的9个常见问题
一般来说,Map是一种由键值对组成的数据结构,其中键(key)在Map中是不能重复的: 本篇文章总结了9个最常见的问题(关于Java Map及其实现类): 出于简单考虑,在代码例子中我将不使用泛型,因 ...
- org.apache.jasper.JasperException: Unable to compile class for JSP
项目启动时报错 : The method getJspApplicationContext(ServletContext) is undefined for the type JspFactory S ...
- centos 安装maven
1.环境: 操作系统:centos7 maven:apache-maven-3.3.9-bin.tar.gz 2.安装JDK(1.7) 3.安装maven mkdir -p /opt/usr/loca ...
- gulp系列:自动构建及刷新浏览器
2016年3月3日 14:50:15 晴 .清空目录 常用插件 gulp-clean .del (nodejs模块)del = require('del')#2.文件复制 原生模块gulp,插 ...
- file
用来测试文件类型 $file [] filename -b列出辨识结果时,但不显示文件名称 -L如果文件是符号链接,那么直接解读其指向的文件 -z:如果文件是压缩文件,尝试去解读压缩文件的内容 $fi ...
- C语言(函数)学习之index、rindex
函数定义:char *index(const char *s, int c); 头文件: #include strings.h 函数说明:index()用来找出参数s 字符串中第一个出现的参数c ...
- [译] OpenStack Kilo 版本中 Neutron 的新变化
OpenStack Kilo 版本,OpenStack 这个开源项目的第11个版本,已经于2015年4月正式发布了.现在是个合适的时间来看看这个版本中Neutron到底发生了哪些变化了,以及引入了哪些 ...
- 实现跨云应用——基于DNS的负载均衡
“公有云可以作为传统IT资源的延展,能帮助客户应对不断变化的需求”——这是我们在向客户介绍公有云产品时经常说的一句话.我们来看一个具体的需求: 某客户有一个web站点,部署在自有的数据中心(on-pr ...
- .Net程序员之Python基础教程学习----列表和元组 [First Day]
一. 通用序列操作: 其实对于列表,元组 都属于序列化数据,可以通过下表来访问的.下面就来看看序列的基本操作吧. 1.1 索引: 序列中的所有元素的下标是从0开始递增的. 如果索引的长度的是N,那么所 ...
- OpenCV 之 图像平滑
1 图像平滑 图像平滑,可用来对图像进行去噪 (noise reduction) 或 模糊化处理 (blurring),实际上图像平滑仍然属于图像空间滤波的一种 (低通滤波) 既然是滤波,则图像中任 ...