一 欣舵、 URLSession 的介紹
1、URLSession在2013年隨著iOS7的發(fā)布一起面世揭鳞,蘋(píng)果對(duì)它的定位是作為NSURLConnection的替代者炕贵。
2、在七層網(wǎng)絡(luò)協(xié)議中有:物理層->數(shù)據(jù)鏈路層->網(wǎng)絡(luò)層->傳輸層->會(huì)話(huà)層->表示層->應(yīng)用層野崇。那我們可以將NSURLSession類(lèi)理解為會(huì)話(huà)層称开,用于管理網(wǎng)絡(luò)接口的創(chuàng)建、維護(hù)乓梨、刪除等等工作鳖轰,我們要做的工作也只是會(huì)話(huà)層之后的層。
二 扶镀、 URLSessionConfiguration 的介紹
1蕴侣、URLSessionConfiguration 的介紹
URLSessionConfiguration 是一個(gè)配置對(duì)象,定義了一個(gè) URL 會(huì)話(huà)的行為和規(guī)則狈惫。
2睛蛛、 URLSessionConfiguration 的三種模式
1、默認(rèn)會(huì)話(huà)模式(default):使用的是基于磁盤(pán)緩存的持久化策略胧谈,使用用戶(hù)keychain中保存的證書(shū)進(jìn)行認(rèn)證授權(quán)忆肾。
2、暫時(shí)會(huì)話(huà)模式(ephemeral): 該模式不使用磁盤(pán)保存任何數(shù)據(jù)菱肖。所有和會(huì)話(huà)相關(guān)的caches客冈,證書(shū),cookies等都被保存在RAM中稳强,因此當(dāng)程序使會(huì)話(huà)無(wú)效场仲,這些緩存的數(shù)據(jù)就會(huì)被自動(dòng)清空和悦。
3、后臺(tái)會(huì)話(huà)模式 (background): 該模式在后臺(tái)完成上傳和下載渠缕,在創(chuàng)建Configuration對(duì)象的時(shí)候需要提供一個(gè)NSString類(lèi)型的ID用于標(biāo)識(shí)完成工作的后臺(tái)會(huì)話(huà)鸽素。
樣式如下:
URLSessionConfiguration.default
URLSessionConfiguration.ephemeral
URLSessionConfiguration.background(withIdentifier: "nw-Session")
三、在下面用到的一些函數(shù)亦鳞,網(wǎng)址編碼/ 數(shù)據(jù)解析
// TODO : 數(shù)據(jù)解析
func nwDataParsing(data:Data) -> Any {
/**
先判斷是否可以解析
*/
return try! JSONSerialization.jsonObject(with: data as Data, options:.mutableContainers)
}
// TODO : 網(wǎng)址編碼處理
func urlEncoding(str:String?) -> String {
if (str != nil) && str!.characters.count != 0 {
return str!.addingPercentEncoding(withAllowedCharacters: .urlFragmentAllowed)!
}
return str!
}
四 馍忽、URLSessionTask 的子類(lèi)關(guān)聯(lián)
各個(gè)類(lèi)的介紹
- URLSessionTask : 一個(gè)可撤銷(xiāo)的對(duì)象,指的是生命周期內(nèi)處理一個(gè)給定的請(qǐng)求。
- URLSessionDataTask : 一個(gè)?數(shù)據(jù)請(qǐng)求?的 URLSessionTask 的子類(lèi)燕差,用于數(shù)據(jù)的請(qǐng)求遭笋。
- URLSessionUploadTask : 是一個(gè)?上傳數(shù)據(jù)?的 URLSessionDataTask 的子類(lèi)。
- URLSessionDownloadTask : 是一個(gè)下載數(shù)據(jù) 的 URLSessionTask 的子類(lèi)徒探。
- URLSessionStreamTask : 是一個(gè)雙向會(huì)話(huà)的 URLSessionTask 的子類(lèi)瓦呼。
五 、URLSession 的 GET 類(lèi)型的請(qǐng)求數(shù)據(jù)
// MARK : 一般的 URLSession 的請(qǐng)求(Get類(lèi)型)
func urlSessionGet() -> Void {
/**
先創(chuàng)建一個(gè)請(qǐng)求鏈接
*/
var linkstr = "https://m.maoyan.com/movie/list.json?type=hot&offset=0&limit=1"
/**
鏈接轉(zhuǎn)碼
*/
linkstr = linkstr.addingPercentEncoding(withAllowedCharacters: .urlFragmentAllowed)!
/**
創(chuàng)建請(qǐng)求網(wǎng)址
*/
let url = URL.init(string: linkstr)
/**
創(chuàng)建請(qǐng)求體
*/
let request = URLRequest.init(url: url!, cachePolicy: .reloadIgnoringCacheData, timeoutInterval: 30)
/**
創(chuàng)建一個(gè)NSURLSession 對(duì)象
*/
let NwSession = URLSession.shared
/**
創(chuàng)建一個(gè) Task 對(duì)象
*/
let NwTask = NwSession.dataTask(with: request) { ( data, urlRespone, error) in
/**
判斷是否有數(shù)據(jù)
*/
if !(data == nil) && (error == nil) {
let Nwdictionary = self.nwDataParsing(data: data!)
print(Nwdictionary)
}
}
/**
開(kāi)啟Task
*/
NwTask.resume()
}
六测暗、URLSession請(qǐng)求下載數(shù)據(jù)
1央串、普通的下載數(shù)據(jù)形式
// MARK : URLSession 的文件下載
func sessionDownloadTask() -> Void {
/**
創(chuàng)建一個(gè)鏈接
*/
var dlStr = "http://files.heweather.com/china-city-list.txt"
/**
網(wǎng)址編碼
*/
dlStr = self.urlEncoding(str: dlStr)
/**
創(chuàng)建請(qǐng)求的網(wǎng)址
*/
let dlUrl = URL.init(string: dlStr)
/**
創(chuàng)建請(qǐng)求體
*/
let request = URLRequest.init(url: dlUrl!)
/**
創(chuàng)建Session對(duì)象
*/
let NwSession = URLSession.shared
/**
創(chuàng)建下載的Task
*/
let loadTask = NwSession.downloadTask(with: request) { (dLoadUrl, response, error) in
/**
下載文件的地址
*/
print(dLoadUrl!)
/**
獲取下載文件的數(shù)據(jù)
*/
let data = try! NSData.init(contentsOfFile: dLoadUrl!.path, options: .mappedIfSafe)
print(String.init(data: data as Data, encoding: .utf8)!)
}
loadTask.resume()
}
2、 帶進(jìn)度條的下載方式
第一偷溺、 帶進(jìn)度的下載首先我們要添加一個(gè)代理 : URLSessionDownloadDelegate
第二蹋辅、編寫(xiě)下載代碼(這里需要有個(gè)注意的地方)
// TODO : 帶進(jìn)度的文件下載
func loadTaskProgress() -> Void {
/**
下載鏈接
*/
let loadUrl = URL.init(string: self.urlEncoding(str: "http://files.heweather.com/china-city-list.txt"))
/**
創(chuàng)建請(qǐng)求體
*/
var request = URLRequest.init(url: loadUrl!)
request .addValue("", forHTTPHeaderField: "Accept-Encoding")
/**
創(chuàng)建URLSession
*/
let NwSession = URLSession.init(configuration: .default, delegate: self, delegateQueue: nil)
/**
開(kāi)始下載
*/
let dTask = NwSession.downloadTask(with: request)
dTask.resume()
}
注意的地方如下:
var request = URLRequest.init(url: loadUrl!)
request .addValue("", forHTTPHeaderField: "Accept-Encoding")'
這里需要這樣書(shū)寫(xiě),否則挫掏,在 URLSessionDownloadDelegate 的代理中** totalBytesExpectedToWrite** 會(huì)一直返回 -1。
第三秩命、URLSessionDownloadDelegate 的代理事件
// MARK : URLSessionDownloadDelegate 的代理事件
// TODO : 下載結(jié)束調(diào)用的代理
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
print("下載結(jié)束")
print("下載地址" + location.path)
}
// TODO : 下載進(jìn)度的監(jiān)聽(tīng)
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
/**
寫(xiě)入字節(jié)
*/
print((CGFloat)(bytesWritten))
/**
已經(jīng)下載的
*/
print((CGFloat)(totalBytesWritten))
/**
總共要下載數(shù)據(jù)的大小
*/
print((CGFloat)(totalBytesExpectedToWrite))
/**
下載進(jìn)度的百分比
*/
print((CGFloat)(totalBytesWritten)/(CGFloat)(totalBytesExpectedToWrite))
print("----------")
}
七 尉共、URLSession 的上傳文件代碼
// MARK : 文件上傳
func sessionUploadTask() -> Void {
/**
創(chuàng)建上傳網(wǎng)址
*/
var uploadStr = ""
uploadStr = self.urlEncoding(str: uploadStr)
let uploadUrl = URL.init(string: uploadStr)
/**
創(chuàng)建請(qǐng)求體
*/
let request = NSMutableURLRequest.init(url: uploadUrl!)
/**
設(shè)置請(qǐng)求的類(lèi)型
*/
request.httpMethod = "POST"
/**
創(chuàng)建session的對(duì)象
*/
let NwSession = URLSession.shared
/**
發(fā)起上傳,以數(shù)據(jù)流的形式弃锐,好處是不限制大小
*/
NwSession.uploadTask(with: request as URLRequest, from: try! Data.init(contentsOf: URL.init(fileURLWithPath: ""))) { (data, urlrequest, error) in
if error == nil {
print(String.init(data: data!, encoding: .utf8)!)
}
}
}
八袄友、 URLSession 的POST 請(qǐng)求
// MARK : URLSession 的POST 請(qǐng)求
func urlSessionPost() -> Void {
/**
請(qǐng)求鏈接
*/
var linkStr = "https://m.maoyan.com/movie/list.json"
/**
網(wǎng)址編碼
*/
linkStr = self.urlEncoding(str: linkStr)
/**
創(chuàng)建請(qǐng)求的URL
*/
let url = URL.init(string: linkStr)
/**
創(chuàng)建請(qǐng)求載體
*/
var request = URLRequest.init(url: url!)
/**
設(shè)置請(qǐng)求的類(lèi)型
*/
request.httpMethod = "POST"
/**
請(qǐng)求參數(shù)
*/
let params = ["type":"hot","offset":0,"limit":2] as [String:Any]
/**
設(shè)置請(qǐng)求的Boby體
*/
request.httpBody = try! JSONSerialization.data(withJSONObject: params, options: .prettyPrinted)
/**
可以發(fā)起請(qǐng)求
*/
let postTask = URLSession.shared.dataTask(with: request) { ( data, response, error) in
if (data != nil) && error == nil {
}
/**
獲取響應(yīng)頭
*/
let mutableResponse = response as! HTTPURLResponse
print(mutableResponse.allHeaderFields)
//[AnyHashable("Content-Type"): text/html;charset=ISO-8859-1, AnyHashable("Content-Length"): 1432, AnyHashable("allow"): GET, AnyHashable("Set-Cookie"): JSESSIONID=v8twzkxoyqvm3speg67sidfh;Path=/;Secure, AnyHashable("content-security-policy"): default-src *.meituan.com *.dianping.com *.qq.com *.gtimg.cn *.gtimg.com *.idqqimg.com *.idqqimg.cn *.tenpay.com *.qpic.cn jsbridge://* js://* 192.168.4.223:9999 cdn.bootcss.com *.maoyan.com *.sankuai.com *.meituan.net *.google-analytics.com wvjbscheme://* imeituan://* meituanmovie://* 'self' 'unsafe-inline' 'unsafe-eval' data:; report-uri http://csp.sankuai.com/reportURL/?bToken=4493e1bb;, AnyHashable("Server"): nginx, AnyHashable("Date"): Wed, 26 Jul 2017 03:40:02 GMT, AnyHashable("Cache-Control"): must-revalidate,no-cache,no-store]
}
/**
開(kāi)始掛起
*/
postTask.resume()
}
九、URLSession 的一些屬性
/**
獲取URLSession的描述
*/
let sessionDescription = URLSession.shared.sessionDescription
print(sessionDescription!)
/**
等待 Task 完成后取消對(duì)相應(yīng)的URLSession
*/
URLSession.shared.finishTasksAndInvalidate()
/**
無(wú)論正在進(jìn)行什么任務(wù)都銷(xiāo)毀對(duì)應(yīng)的URLSession
*/
URLSession.shared.invalidateAndCancel()
/**
清空所有的Cookies,緩存和證書(shū)存儲(chǔ),刪除磁盤(pán)文件,將正在進(jìn)行的下載到磁盤(pán),并確保未來(lái)發(fā)生在一個(gè)新的套接字的請(qǐng)求霹菊。
*/
URLSession.shared.reset {
print("one new URLSession")
}
/**
將Cookies和證書(shū)保存到磁盤(pán),清除臨時(shí)緩存,并確保未來(lái)發(fā)生在一個(gè)新的TCP連接請(qǐng)求剧蚣。
*/
URLSession.shared.flush {
print("one new URLSession")
}
/*
注意: flush & reset 的異同。相同: 都是清楚當(dāng)前的URLSession,確保下次創(chuàng)建一個(gè)新的Session旋廷。 不同: flush 再清除的緩存時(shí)鸠按,保留cookie和證書(shū)。而 reset 什么都不保留饶碘。
*/