Загрузка данных — NSURLSession
До выхода iOS 7.0 единственным интерфейсом для загрузки данных по сети служил класс NSURLConnection, затем был добавлен NSURLSession, который со временем стал полноценным преемником, обладающим расширенными и более гибкими возможностями. Начиная с iOS 9.0 NSURLConnection более не рекомендуется использовать.
NSURLSession поддерживает основные протоколы передачи информации, в том числе защищенные. Работа осуществляется как с обычными файлами, так и объектами NSData.
Для простых задач у класса есть метод NSURLSession.sharedSession(), возвращающий преднастроенный синглтон-экземпляр. Настройки по умолчанию достаточно оптимальны, единственным серьезным минусом является невозможность задать делегата, отслеживающего все события процесса, а не только завершение загрузки посредством функции-обработчика.
import Foundation
import XCPlayground
// Playground configuration
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
let url = NSURL(string: "http://valery.bashkatov.org/favicon.png")!
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url,
completionHandler:
// This function is called when the task is completed
{
(data: NSData?,
response: NSURLResponse?,
error: NSError?) -> Void in
if error == nil {
print("Downloading completed")
} else {
print(error)
}
})
// Run task
task.resume()
Если же требования выше, NSURLSession конфигурируется через объект NSURLSessionConfiguration. Сначала необходимо создать одну из базовых конфигураций вызовом соответствующего метода класса (возвращается новый экземпляр, а не синглтон):
- NSURLSessionConfiguration.defaultSessionConfiguration() — включает настройки по умолчанию, для кэширования используется диск.
- NSURLSessionConfiguration.ephemeralSessionConfiguration() — аналогично defaultSessionConfiguration за исключением кэширования, все хранится только в оперативной памяти.
- NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier(_ identifier: String) — загрузка осуществляется в фоновом режиме даже при неактивном приложении, кроме того, после внештатного завершения задание может быть продолжено по идентификатору. Этот режим обладает рядом ограничений.
Затем возможно изменить неустраивающие значения свойств.
Во время инициализации NSURLSession разрешается также указать делегата, получающего контроль над процессом загрузки через реализацию протоколов:
- NSURLSessionDelegate — для событий сессии;
- NSURLSessionTaskDelegate — общих событий всех заданий;
- NSURLSessionDataDelegate — событий заданий с объектами NSData и отправки файлов;
- NSURLSessionDownloadDelegate — событий заданий получения файлов.
import UIKit
class ViewController: UIViewController, NSURLSessionDataDelegate {
var data: NSMutableData!
var dataURL: NSURL!
var session: NSURLSession!
var sessionConfiguration: NSURLSessionConfiguration!
var sessionTask: NSURLSessionDataTask!
override func viewDidLoad() {
super.viewDidLoad()
data = NSMutableData()
dataURL = NSURL(string: "http://valery.bashkatov.org/favicon.png")!
// Used ephemeral session for disable disk-based cache
sessionConfiguration = NSURLSessionConfiguration.ephemeralSessionConfiguration()
sessionConfiguration.timeoutIntervalForRequest = 10
session = NSURLSession(configuration: sessionConfiguration,
delegate: self,
delegateQueue: nil)
sessionTask = session.dataTaskWithURL(dataURL)
sessionTask.resume()
}
// Method defined in NSURLSessionDataDelegate protocol
func URLSession(session: NSURLSession,
dataTask: NSURLSessionDataTask,
didReceiveResponse response: NSURLResponse,
completionHandler: (NSURLSessionResponseDisposition) -> Void) {
print("Received server response")
print("Expected file size: \(response.expectedContentLength) bytes")
completionHandler(NSURLSessionResponseDisposition.Allow)
print("Downloading started")
}
// Method defined in NSURLSessionDataDelegate protocol
func URLSession(session: NSURLSession,
dataTask: NSURLSessionDataTask,
didReceiveData data: NSData) {
print(" Received: \(data.length) bytes")
// Collect full data, chunk by chunk
data.enumerateByteRangesUsingBlock
{
[unowned self] (bytes: UnsafePointer<Void>,
byteRange: NSRange,
stop: UnsafeMutablePointer<ObjCBool>) in
self.data.appendBytes(bytes, length: byteRange.length)
}
}
// Method defined in NSURLSessionTaskDelegate protocol
func URLSession(session: NSURLSession,
task: NSURLSessionTask,
didCompleteWithError error: NSError?) {
guard error == nil else {
print(error)
return
}
print("Downloading completed")
}
}