很多同學(xué)在遇到要使用網(wǎng)絡(luò)請求的時候,無腦Alamofire,不是說這個庫不好用。畢竟第三方,畢竟還要學(xué)習他得使用方法,還要引入他得代碼。為何不嘗試下使用NSURLSession,以前NSURLConnection操作起來有很多不便,大家可能都愿意使用第三方庫。但是現(xiàn)在的NSURLSession使用起來已經(jīng)很方便了。我們何不利用學(xué)習Alamofire的時間來學(xué)習學(xué)習NSURLSession呢?第三方庫也許有很多對json處理方便的加強功能,但是我們有時候只需要用他來做get , put ,post delete 請求 。還有一些下載上傳 、斷點下載等功能 其實NSURLSession已經(jīng)夠用了。
最簡單的調(diào)用
if let url = NSURL(string: "https://httpbin.org/get") {
NSURLSession.sharedSession().dataTaskWithURL(url){ data, response, error in
//...
}.resume()
}
拿到一個 url 獲取默認的session來處理url返回我們想要的數(shù)據(jù)
resume() 方法的調(diào)用,NSURLSession 默認是不啟動的,我們必須手工調(diào)用 resume() 方法,才會開始請求
NSURLSession 本身是不會進行請求的,而是通過創(chuàng)建 task 的形式進行網(wǎng)絡(luò)請求,同一個 NSURLSession 可以創(chuàng)建多個 task,并且這些 task 之間的 cache 和 cookie 是共享的。那么我們就來看看 NSURLSession 都能創(chuàng)建哪些 task 吧。
NSURLSessionDataTask: 這個就是我們第一個例子中創(chuàng)建的 DataTask,它主要用于讀取服務(wù)端的簡單數(shù)據(jù),比如 JSON 數(shù)據(jù)。其實這個請求不只是可以去數(shù)據(jù),修改,新增都是可以的,put , post
NSURLSessionDownloadTask: 這個 task 的主要用途是進行文件下載,它針對大文件的網(wǎng)絡(luò)請求做了更多的處理,比如下載進度,斷點續(xù)傳等等。
NSURLSessionUploadTask: 和下載任務(wù)對應(yīng),這個 task 主要是用于對服務(wù)端發(fā)送文件類型的數(shù)據(jù)使用的。

那么NSURLSession只能通過NSURLSession.sharedSession()獲得嗎? -- NO,NSURLSession很強大 也是高度可配置的
NSURLSessionConfiguration
我們還可以通過NSURLSessionConfiguration來創(chuàng)建一個NSURLSession 。有三種配置類型可供我們選擇
- defaultSessionConfiguration - 這個配置會使用全局的緩存,cookie 等信息,這個相當于 NSURLSessionConfiguration 的默認配置行為。
- ephemeralSessionConfiguration - 這個配置不會對緩存或 cookie 以及認證信息進行存儲,相當于一個私有的 Session,如果你開發(fā)一個瀏覽器產(chǎn)品,這個配置就相當于瀏覽器的隱私模式。
- backgroundSessionConfiguration - 這個配置可以讓你的網(wǎng)絡(luò)操作在你的應(yīng)用切換到后臺的時候還能繼續(xù)工作。
整個結(jié)構(gòu)大概就是這樣的

NSURLSessionConfiguration 還支持配置session的一些屬性,比如timeout 、cache添加http header等,可以在這里 查閱所有可配置信息
那么我們來嘗試創(chuàng)建一個任務(wù)
//定義一個默認的session
lazy var defaultSession = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration())
//獲取data的task
var dataTask:NSURLSessionDataTask?
/**
任務(wù)
*/
func doTask(){
guard let url = NSURL(string: "http://your.url") else { return }
dataTask = defaultSession.dataTaskWithURL(url)
dataTask?.resume()
}
這個例子 跟上面的簡單例子如出一轍,不過時我們自己創(chuàng)建的session,把步驟分開了。
看看如何去配置呢
func doTask2(){
let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
configuration.timeoutIntervalForRequest = 10 //超時時間
configuration.requestCachePolicy = .UseProtocolCachePolicy //緩存策略
configuration.HTTPAdditionalHeaders = ["Content-Type":"application/json"] //header 配置
//更多配置詳見官方文檔...
let defaultSession2 = NSURLSession(configuration:configuration)
//獲取data的task
var dataTask:NSURLSessionDataTask?
guard let url = NSURL(string: "http://your.url") else { return }
let request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "get" //post put delete 等
//還有很多可以設(shè)置 更多設(shè)置 詳細 command + 點擊 NSMutableURLRequest 就可以看到了
dataTask = defaultSession2.dataTaskWithRequest(request, completionHandler: { (data, response, error) -> Void in
//操作數(shù)據(jù)
})
dataTask?.resume() //開啟任務(wù)
}
我們可以對configuration和request進行配置 來達到我們想要的目的
對請求的操作室基于task的 這里的task也是可以cancel的
那么下載呢?
lazy var downloadsSession:NSURLSession = {
let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
//delegateQueue設(shè)置為nil session會自己創(chuàng)建一個串行的隊列
return NSURLSession(configuration: configuration, delegate: self, delegateQueue: nil)
}()
下載創(chuàng)建session和普通的請求差不多,我們這里添加了代理就可以拿到下載進度
func doDownload(){
guard let url = NSURL(string: "http://your.download.url") else { return }
let downloadTask = downloadsSession.downloadTaskWithURL(url)
downloadTask.resume()
}
完成回調(diào)可以用閉包 也可以代理。但是要拿到下載進度 必須用代理了
class yourClass:NSURLSessionDownloadDelegate{
func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didFinishDownloadingToURL location: NSURL) {
print("下載完成")
if let originalURL = downloadTask.originalRequest?.URL?.absoluteString,destinationURL = localFilePathForUrl(originalURL){
print("本地的臨時地址 : \(destinationURL)")
let fileManager = NSFileManager.defaultManager()
do {
try fileManager.removeItemAtURL(destinationURL)
} catch let error as NSError {
print("Error: \(error.localizedDescription)")
}
do {
try fileManager.copyItemAtURL(location, toURL: destinationURL)
} catch let error as NSError {
print("Error: \(error.localizedDescription)")
}
}
}
/**
監(jiān)控下載進度
*/
func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
if let downloadUrl = downloadTask.originalRequest?.URL?.absoluteString,download = activeDownloads[downloadUrl]{
download.progress = Float(totalBytesWritten)/Float(totalBytesExpectedToWrite)
let totalSize = NSByteCountFormatter.stringFromByteCount(totalBytesExpectedToWrite, countStyle: NSByteCountFormatterCountStyle.Binary)
if let trackIndex = trackIndexForDownloadTask(downloadTask),trackCell = tableView.cellForRowAtIndexPath(NSIndexPath(forRow: trackIndex, inSection: 0)) as? TrackCell{
}
}
}
當然下載過程中也是可以取消的 直接調(diào)用task.cancel()
如果需要暫停
task.cancelByProducingResumeData { data in
if data != nil {
//將data保存本地 或者 內(nèi)存
}
}
繼續(xù)下載
//resumeData 為上次保存的data
task = downloadsSession.downloadTaskWithResumeData(resumeData)
task.resume()
上傳參照下載。。
本文參照 以及推薦擴展閱讀http://www.raywenderlich.com/110458/nsurlsession-tutorial-getting-started
http://swiftcafe.io/2015/12/20/nsurlsession/
http://swiftcafe.io/2015/12/23/nsurlsession-app/
http://www.itdecent.cn/p/fb5aaeac06ef
建議大家去讀下raywenderlich的這片文章 講的很細