51 -Swift 之 URLSession網(wǎng)絡(luò)請(qǐng)求

一 欣舵、 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)

2E921CC8-5035-48D5-B499-FEDF9EADED29.png

各個(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 什么都不保留饶碘。
 */
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末目尖,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子扎运,更是在濱河造成了極大的恐慌瑟曲,老刑警劉巖饮戳,帶你破解...
    沈念sama閱讀 218,451評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異洞拨,居然都是意外死亡扯罐,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)烦衣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)篮赢,“玉大人,你說(shuō)我怎么就攤上這事琉挖∑羝” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,782評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵示辈,是天一觀(guān)的道長(zhǎng)寥茫。 經(jīng)常有香客問(wèn)我,道長(zhǎng)矾麻,這世上最難降的妖魔是什么纱耻? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,709評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮险耀,結(jié)果婚禮上弄喘,老公的妹妹穿的比我還像新娘。我一直安慰自己甩牺,他們只是感情好蘑志,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,733評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著贬派,像睡著了一般急但。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上搞乏,一...
    開(kāi)封第一講書(shū)人閱讀 51,578評(píng)論 1 305
  • 那天波桩,我揣著相機(jī)與錄音,去河邊找鬼请敦。 笑死镐躲,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的侍筛。 我是一名探鬼主播萤皂,決...
    沈念sama閱讀 40,320評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼勾笆!你這毒婦竟也來(lái)了敌蚜?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,241評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤窝爪,失蹤者是張志新(化名)和其女友劉穎弛车,沒(méi)想到半個(gè)月后齐媒,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,686評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡纷跛,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,878評(píng)論 3 336
  • 正文 我和宋清朗相戀三年喻括,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片贫奠。...
    茶點(diǎn)故事閱讀 39,992評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡唬血,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出唤崭,到底是詐尸還是另有隱情拷恨,我是刑警寧澤,帶...
    沈念sama閱讀 35,715評(píng)論 5 346
  • 正文 年R本政府宣布谢肾,位于F島的核電站腕侄,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏芦疏。R本人自食惡果不足惜冕杠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,336評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望酸茴。 院中可真熱鬧分预,春花似錦、人聲如沸薪捍。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,912評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)飘诗。三九已至与倡,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間昆稿,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,040評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工息拜, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留溉潭,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,173評(píng)論 3 370
  • 正文 我出身青樓少欺,卻偏偏與公主長(zhǎng)得像喳瓣,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子赞别,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,947評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容