Используя NSURLSession
NSURLSession
класс и связанные классы обеспечивают API для загрузки содержания через HTTP. Этот API обеспечивает богатый набор методов делегата для поддержки аутентификации и предоставляет Вашему приложению возможность выполнить фоновые загрузки, когда Ваше приложение не работает или в iOS, в то время как приостановлено Ваше приложение.
Использовать NSURLSession
API, Ваше приложение создает серию сеансов, каждый из которых координирует группу связанных задач передачи данных. Например, если Вы пишете веб-браузер, Ваше приложение могло бы создать один сеанс на вкладку или окно. В каждом сеансе Ваше приложение добавляет серию задач, каждая из которых представляет запрос на определенный URL (и на любой последующий URLs, если исходный URL возвратил перенаправление HTTP).
Как самый сетевой APIs, NSURLSession
API является очень асинхронным. При использовании значения по умолчанию, предоставленного системой делегата, необходимо обеспечить блок обработчика завершения, возвращающий данные приложению, когда передача заканчивается успешно или с ошибкой. Также при обеспечении собственных объектов делегата объекты задачи вызывают методы тех делегатов с данными, поскольку они получены от сервера (или, для загрузок файла, когда передача завершена).
NSURLSession
API обеспечивает состояние и свойства прогресса, в дополнение к поставке этой информации делегатам. Это поддерживает отмену, перезапуск (возобновления) и приостановку задач, и это предоставляет возможность для возобновления приостановленных, отмененных, или отказавших загрузок, где они кончили.
Понимание понятий сеанса URL
Поведение задач в сеансе зависит от трех вещей: тип сеанса (определенный типом объекта конфигурации раньше создавал его), тип задачи, и было ли приложение на переднем плане, когда создавалась задача.
Типы сеансов
NSURLSession
API поддерживает три типа сеансов, как определено типом объекта конфигурации, используемого для создания сеанса:
Сеансы по умолчанию ведут себя так же к другим методам Основы для загрузки URLs. Они используют персистентный находящийся на диске кэш и хранят учетные данные в цепочке для ключей пользователя.
Эфемерные сеансы не хранят данных к диску; все кэши, учетные хранилища, и т.д. сохранены в RAM и связаны к сеансу. Таким образом, когда Ваше приложение лишает законной силы сеанс, они очищены автоматически.
Фоновые сеансы подобны сеансам по умолчанию, за исключением того, что отдельный процесс обрабатывает всю передачу данных. Фоновые сеансы имеют некоторые дополнительные ограничения, описанные в Фоновых Соображениях Передачи.
Типы задач
В сеансе, NSURLSession
класс поддерживает три типа задач: задачи данных, задачи загрузки и задачи загрузки.
Задачи данных отправляют и получают использование данных
NSData
объекты. Задачи данных предназначаются для краткости часто интерактивные запросы с Вашего приложения на сервер. Задачи данных могут возвратить данные Вашему приложению одна часть за один раз после того, как каждая часть данных будет получена, или одновременно через обработчик завершения. Поскольку задачи данных не хранят данные к файлу, они не поддерживаются в фоновых сеансах.В то время как приложение не работает, задачи загрузки получают данные в форме файла и поддерживают фоновые загрузки.
В то время как приложение не работает, задачи загрузки отправляют данные (обычно в форме файла) и поддерживают фоновые загрузки.
Фоновые соображения передачи
NSURLSession
в то время как Ваше приложение приостановлено, класс поддерживает фоновые передачи. Фоновые передачи предоставлены только сеансами, создаваемыми с помощью фонового объекта конфигурации сеанса (как возвращено вызовом к backgroundSessionConfiguration:
).
С фоновыми сеансами, потому что фактическая передача выполняется отдельным процессом и потому что перезапуск процесса Вашего приложения является относительно дорогим, несколько функций недоступны, приводя к следующим ограничениям:
Сеанс должен предоставить делегату к поставке события. (Для загрузок и загрузок, делегаты ведут себя то же что касается незавершенных передач.)
Только HTTP и протоколы HTTPS поддерживаются (никакие пользовательские протоколы).
Только загрузка и задачи загрузки поддерживаются (никакие задачи данных).
Перенаправления всегда сопровождаются.
В то время как приложение в фоновом режиме, объект конфигурации, если инициируется фоновая передача
discretionary
свойство обрабатывается как являющийсяtrue
.
Путем Ваше приложение ведет себя, когда оно повторно запускается, отличается немного между iOS и OS X.
В iOS, когда фоновая передача завершает или требует учетных данных, если Ваше приложение больше не работает, iOS автоматически повторно запускает Ваше приложение в фоновом режиме и вызывает application:handleEventsForBackgroundURLSession:completionHandler:
метод на Вашем приложении UIApplicationDelegate
объект. Этот вызов обеспечивает идентификатор сеанса, заставившего Ваше приложение быть запущенным. Ваше приложение должно сохранить тот обработчик завершения, создать фоновый объект конфигурации с тем же идентификатором и создать сеанс с тем объектом конфигурации. Новый сеанс автоматически повторно связан с продолжающимся фоновым действием. Позже, когда сеанс заканчивает последнюю фоновую задачу загрузки, он отправляет делегата сеанса a URLSessionDidFinishEventsForBackgroundURLSession:
сообщение. Ваш делегат сеанса должен тогда вызвать сохраненный обработчик завершения.
И в iOS и в OS X, когда пользователь повторно запускает Ваше приложение, Ваше приложение должно сразу создать фоновые объекты конфигурации с теми же идентификаторами как любые сеансы, имевшие выдающиеся задачи, когда Ваше приложение в последний раз работало, затем создайте сеанс для каждого из тех объектов конфигурации. Эти новые сеансы так же автоматически повторно связаны с продолжающимся фоновым действием.
В то время как Ваше приложение было приостановлено, делегат, если завершилась какая-либо задача URLSession:downloadTask:didFinishDownloadingToURL:
метод тогда вызывают с задачей и URL для недавно загруженного файла, связанного с ним.
Точно так же, если какая-либо задача требует учетных данных, NSURLSession
вызовы объектов делегат URLSession:task:didReceiveChallenge:completionHandler:
метод или URLSession:didReceiveChallenge:completionHandler:
метод как надлежащий.
Для примера того, как использовать NSURLSession
для фоновых передач посмотрите Простую Фоновую Передачу.
Жизненный цикл и взаимодействие делегата
В зависимости от какого Вы делаете с NSURLSession
класс, может быть полезно полностью понять жизненный цикл сеанса, включая то, как сеанс взаимодействует со своим делегатом, порядком, в котором выполняются вызовы делегата, что происходит, когда сервер возвращает перенаправление, что происходит, когда Ваше приложение возобновляет неработающую загрузку и т.д.
Для полного описания жизненного цикла сеанса URL считайте Жизненный цикл Сеанса URL.
Поведение NSCopying
Сеанс и объекты задачи соответствуют NSCopying
протокол следующим образом:
Когда Ваши копии приложений сеанс или объект задачи, Вы возвращаете тот же объект.
Когда Ваши копии приложений объект конфигурации, Вы получаете новую копию, которую можно независимо изменить.
Демонстрационный интерфейс класса делегата
Фрагменты кода в следующих разделах задачи основываются на интерфейсе класса, показанном в Перечислении 1-1.
Выборка перечисления 1-1 делегирует интерфейс класса
#import <Foundation/Foundation.h> |
typedef void (^CompletionHandlerType)(); |
@interface MySessionDelegate : NSObject <NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDataDelegate, NSURLSessionDownloadDelegate> |
@property NSURLSession *backgroundSession; |
@property NSURLSession *defaultSession; |
@property NSURLSession *ephemeralSession; |
#if TARGET_OS_IPHONE |
@property NSMutableDictionary *completionHandlerDictionary; |
#endif |
- (void) addCompletionHandler: (CompletionHandlerType) handler forSession: (NSString *)identifier; |
- (void) callCompletionHandlerForSession: (NSString *)identifier; |
@end |
Создание и конфигурирование сеанса
NSURLSession
API обеспечивает широкий диапазон параметров конфигурации:
Частная поддержка хранения кэшей, cookie, учетных данных и протоколов в пути, который является определенным для единственного сеанса
Аутентификация, связанная к определенному запросу (задача) или группа запросов (сеанс)
Загрузки файла и загрузки URL, мотивирующим разделение данных (содержание файла) от метаданных (URL и настройки)
Конфигурация максимального количества соединений на узел
Тайм-ауты на ресурс, инициированные, если весь ресурс не может быть загружен в определенной сумме времени
Минимальная и максимальная поддержка версии TLS
Пользовательские словари прокси
Управление политиками cookie
Управление поведением конвейерной обработки HTTP
Поскольку большинство настроек содержится в отдельном объекте конфигурации, можно снова использовать обычно используемые настройки. При инстанцировании объекта сеанса Вы указываете следующее:
Объект конфигурации, управляющий поведением того сеанса и задач в нем
Дополнительно, объект делегата обработать входящие данные, поскольку это получено и обрабатывает другие события, определенные для сеанса и задач в нем, таких как аутентификация сервера, определяя, должен ли запрос загрузки ресурса быть преобразован в загрузку и т.д.
Если Вы не предоставляете делегату,
NSURLSession
возразите использует предоставленного системой делегата. Таким образом можно с готовностью использоватьNSURLSession
вместо существующего кода, использующегоsendAsynchronousRequest:queue:completionHandler:
удобный метод дляNSURLSession
.
После инстанцирования объекта сеанса Вы не можете изменить конфигурацию или делегата, не создавая новый сеанс.
Перечисление 1-2 показывает примеры того, как создать нормальные, эфемерные, и фоновые сеансы.
Перечисление 1-2 Создающие и конфигурирующие сеансы
#if TARGET_OS_IPHONE |
self.completionHandlerDictionary = [NSMutableDictionary dictionaryWithCapacity:0]; |
#endif |
/* Create some configuration objects. */ |
NSURLSessionConfiguration *backgroundConfigObject = [NSURLSessionConfiguration backgroundSessionConfiguration: @"myBackgroundSessionIdentifier"]; |
NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration]; |
NSURLSessionConfiguration *ephemeralConfigObject = [NSURLSessionConfiguration ephemeralSessionConfiguration]; |
/* Configure caching behavior for the default session. |
Note that iOS requires the cache path to be a path relative |
to the ~/Library/Caches directory, but OS X expects an |
absolute path. |
*/ |
#if TARGET_OS_IPHONE |
NSString *cachePath = @"/MyCacheDirectory"; |
NSArray *myPathList = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); |
NSString *myPath = [myPathList objectAtIndex:0]; |
NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier]; |
NSString *fullCachePath = [[myPath stringByAppendingPathComponent:bundleIdentifier] stringByAppendingPathComponent:cachePath]; |
NSLog(@"Cache path: %@\n", fullCachePath); |
#else |
NSString *cachePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"/nsurlsessiondemo.cache"]; |
NSLog(@"Cache path: %@\n", cachePath); |
#endif |
NSURLCache *myCache = [[NSURLCache alloc] initWithMemoryCapacity: 16384 diskCapacity: 268435456 diskPath: cachePath]; |
defaultConfigObject.URLCache = myCache; |
defaultConfigObject.requestCachePolicy = NSURLRequestUseProtocolCachePolicy; |
/* Create a session for each configurations. */ |
self.defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: self delegateQueue: [NSOperationQueue mainQueue]]; |
self.backgroundSession = [NSURLSession sessionWithConfiguration: backgroundConfigObject delegate: self delegateQueue: [NSOperationQueue mainQueue]]; |
self.ephemeralSession = [NSURLSession sessionWithConfiguration: ephemeralConfigObject delegate: self delegateQueue: [NSOperationQueue mainQueue]]; |
За исключением фоновых конфигураций, можно снова использовать объекты конфигурации сеанса создать дополнительные сеансы. (Вы не можете снова использовать фоновые конфигурации сеанса, потому что поведение двух фоновых объектов сеанса, совместно использующих тот же идентификатор, не определено.)
В любое время можно также безопасно изменить объекты конфигурации. При создании сеанса сеанс выполняет глубокую копию на объекте конфигурации, таким образом, модификации влияют только на новые сеансы, не существующие сеансы. Например, Вы могли бы создать второй сеанс для содержания, которое должно быть получено, только если Вы находитесь на соединении Wi-Fi как показано в Перечислении 1-3.
Перечисление 1-3 , Создающее второй сеанс с тем же объектом конфигурации
ephemeralConfigObject.allowsCellularAccess = YES; |
// ... |
NSURLSession *ephemeralSessionWiFiOnly = [NSURLSession sessionWithConfiguration: ephemeralConfigObject delegate: self delegateQueue: [NSOperationQueue mainQueue]]; |
Выбирающие ресурсы Используя предоставленных системой делегатов
Самый прямой способ использовать NSURLSession
как понижение замены для sendAsynchronousRequest:queue:completionHandler:
метод на NSURLSession
. Используя этот подход, Ваша потребность обеспечить только две части кода в Вашем приложении:
Код для создания конфигурации возражает и сеанс на основе того объекта
Подпрограмма обработчика завершения, чтобы сделать что-то с данными после того, как это было полностью получено
Используя предоставленных системой делегатов, можно выбрать определенный URL только с одной строкой кода на запрос. Перечисление 1-4 показывает пример этой упрощенной формы.
Перечисление 1-4 , Запрашивающее ресурс с помощью предоставленный системой делегатов
NSURLSession *delegateFreeSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: nil delegateQueue: [NSOperationQueue mainQueue]]; |
[[delegateFreeSession dataTaskWithURL: [NSURL URLWithString: @"http://www.example.com/"] |
completionHandler:^(NSData *data, NSURLResponse *response, |
NSError *error) { |
NSLog(@"Got response %@ with error %@.\n", response, error); |
NSLog(@"DATA:\n%@\nEND DATA\n", |
[[NSString alloc] initWithData: data |
encoding: NSUTF8StringEncoding]); |
}] resume]; |
Выборка данных Используя пользовательского делегата
Если Вы используете пользовательского делегата для получения данных, делегат должен реализовать, по крайней мере, следующие методы:
URLSession:dataTask:didReceiveData:
предоставляет данные от запроса до Вашей задачи, одна часть за один раз.URLSession:task:didCompleteWithError:
указывает к Вашей задаче, что были полностью получены данные.
Если Ваше приложение должно использовать данные после URLSession:dataTask:didReceiveData:
возвраты метода, Ваш код ответственен за то, что хранил данные в некотором роде.
Например, веб-браузер, возможно, должен был бы представить данные, когда это поступает вместе с любыми данными, которые это ранее получило. Чтобы сделать это, это могло бы использовать словарь, отображающий объект задачи на NSMutableData
объект для хранения результатов, и затем использует appendData:
метод на том объекте добавить недавно полученные данные.
Перечисление 1-5 показывает, как Вы создаете и запускаете задачу данных.
Пример задачи Данных перечисления 1-5
NSURL *url = [NSURL URLWithString: @"http://www.example.com/"]; |
NSURLSessionDataTask *dataTask = [self.defaultSession dataTaskWithURL: url]; |
[dataTask resume]; |
Загрузка файлов
На высоком уровне, загружая файл подобно получению данных. Ваше приложение должно реализовать следующие методы делегата:
URLSession:downloadTask:didFinishDownloadingToURL:
предоставляет Вашему приложению URL к временному файлу, где сохранено загруженное содержание.URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:
предоставляет Вашему приложению информацию о статусе о прогрессе загрузки.URLSession:downloadTask:didResumeAtOffset:expectedTotalBytes:
говорит Вашему приложению, что его попытка возобновить ранее неработающую загрузку была успешна.URLSession:task:didCompleteWithError:
говорит Вашему приложению, что загрузка перестала работать.
Когда приложение не работает, при планировании загрузки в фоновом сеансе загрузка продолжается. Когда приложение повторно запускается, при планировании загрузки в стандартном или эфемерном сеансе загрузка должна начаться снова.
Во время передачи от сервера, если пользователь говорит Вашему приложению приостанавливать загрузку, Ваше приложение может отменить задачу путем вызова cancelByProducingResumeData:
метод. Позже, Ваше приложение может передать возвращенные данные резюме любому downloadTaskWithResumeData:
или downloadTaskWithResumeData:completionHandler:
метод для создания новой задачи загрузки, продолжающей загрузку.
Если передача перестала работать, Ваш делегат URLSession:task:didCompleteWithError:
метод вызывают с NSError
объект. Если задача resumable, что объект userInfo
словарь содержит значение для NSURLSessionDownloadTaskResumeData
ключ. Ваше приложение должно использовать достижимость APIs для определения, когда повторить и должно тогда вызвать downloadTaskWithResumeData:
или downloadTaskWithResumeData:completionHandler:
создать новую задачу загрузки продолжать ту загрузку.
Перечисление 1-6 обеспечивает пример загрузки умеренно большого файла. Перечисление 1-7 обеспечивает пример методов делегата задачи загрузки.
Пример задачи Загрузки перечисления 1-6
NSURL *url = [NSURL URLWithString: @"/RU/iOS/documentation/Cocoa/Reference/" |
"Foundation/ObjC_classic/FoundationObjC.pdf"]; |
NSURLSessionDownloadTask *downloadTask = [self.backgroundSession downloadTaskWithURL: url]; |
[downloadTask resume]; |
Методы делегата перечисления 1-7 для задач загрузки
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location |
{ |
NSLog(@"Session %@ download task %@ finished downloading to URL %@\n", |
session, downloadTask, location); |
#if 0 |
/* Workaround */ |
[self callCompletionHandlerForSession:session.configuration.identifier]; |
#endif |
#define READ_THE_FILE 0 |
#if READ_THE_FILE |
/* Open the newly downloaded file for reading. */ |
NSError *err = nil; |
NSFileHandle *fh = [NSFileHandle fileHandleForReadingFromURL:location |
error: &err]; |
/* Store this file handle somewhere, and read data from it. */ |
// ... |
#else |
NSError *err = nil; |
NSFileManager *fileManager = [NSFileManager defaultManager]; |
NSString *cacheDir = [[NSHomeDirectory() |
stringByAppendingPathComponent:@"Library"] |
stringByAppendingPathComponent:@"Caches"]; |
NSURL *cacheDirURL = [NSURL fileURLWithPath:cacheDir]; |
if ([fileManager moveItemAtURL:location |
toURL:cacheDirURL |
error: &err]) { |
/* Store some reference to the new URL */ |
} else { |
/* Handle the error. */ |
} |
#endif |
} |
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite |
{ |
NSLog(@"Session %@ download task %@ wrote an additional %lld bytes (total %lld bytes) out of an expected %lld bytes.\n", |
session, downloadTask, bytesWritten, totalBytesWritten, totalBytesExpectedToWrite); |
} |
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes |
{ |
NSLog(@"Session %@ download task %@ resumed at offset %lld bytes out of an expected %lld bytes.\n", |
session, downloadTask, fileOffset, expectedTotalBytes); |
} |
Загрузка содержания организации
Ваше приложение может обеспечить содержание организации запроса для HTTP запрос POST тремя способами: как NSData
объект, как файл, или как поток. В целом Ваше приложение должно:
Используйте
NSData
возразите, имеет ли Ваше приложение уже данные в памяти и не имеет никакой причины избавиться от него.Используйте файл, если содержание, которое Вы загружаете, существует как файл на диске или если это к преимуществу Вашего приложения для записи его в диск так, чтобы это могло выпустить память, связанную с теми данными.
Используйте поток, если Вы получаете данные по сети или преобразовываете существующий
NSURLConnection
код, предоставляющий организации запроса как потоку.
Независимо от которого стиля Вы выбираете, если Ваше приложение предоставляет пользовательскому делегату сеанса, тот делегат должен реализовать URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:
метод делегата получить загружает информацию прогресса.
Кроме того, если Ваше приложение предоставляет организации запроса с помощью потока, это должно предоставить пользовательскому делегату сеанса, реализующему URLSession:task:needNewBodyStream:
метод, описанный более подробно в Загрузке Содержания Организации Используя Поток.
Загрузка содержания организации Используя объект NSData
Загружать содержание организации с NSData
объект, Ваше приложение вызывает любого uploadTaskWithRequest:fromData:
или uploadTaskWithRequest:fromData:completionHandler:
метод для создания задачи загрузки, и предоставляет данные организации запроса через fromData
параметр.
Объект сеанса вычисляет Content-Length
заголовок на основе размера объекта данных.
Ваше приложение должно обеспечить любую дополнительную информацию заголовка, которой сервер мог бы потребовать — тип контента, например — как часть объекта URL-запроса.
Загрузка содержания организации Используя файл
Для загрузки содержания организации от файла приложение вызывает любого uploadTaskWithRequest:fromFile:
или uploadTaskWithRequest:fromFile:completionHandler:
метод для создания задачи загрузки, и обеспечивает файл URL, из которого задача читает содержание организации.
Объект сеанса вычисляет Content-Length
заголовок на основе размера объекта данных. Если Ваше приложение не обеспечивает значение для Content-Type
заголовок, сеанс также обеспечивает тот.
Ваше приложение может обеспечить любую дополнительную информацию заголовка, которой сервер мог бы потребовать как часть объекта URL-запроса.
Загрузка содержания организации Используя поток
Для загрузки содержания организации использование потока приложение вызывает uploadTaskWithStreamedRequest:
метод для создания задачи загрузки. Ваше приложение предоставляет объекту запроса связанный поток, из которого задача читает содержание организации.
Ваше приложение должно обеспечить любую дополнительную информацию заголовка, которой сервер мог бы потребовать — тип контента и длина, например — как часть объекта URL-запроса.
Кроме того, потому что сеанс не может обязательно перемотать предоставленный поток для перечитывания данных, приложение ответственно за обеспечение нового потока, если сеанс должен повторить запрос (например, если аутентификация перестала работать). Чтобы сделать это, Ваше приложение обеспечивает a URLSession:task:needNewBodyStream:
метод. Когда тот метод вызывают, Ваше приложение должно выполнить любые действия, необходимы, чтобы получить или создать новый поток организации, и затем вызвать предоставленный блок обработчика завершения с новым потоком.
Загрузка файла Используя задачу загрузки
Для загрузки содержания организации для задачи загрузки приложение должно предоставить любому NSData
возразите или поток организации как часть NSURLRequest
объект обеспечил, когда он создает запрос загрузки.
При обеспечении данных с помощью потока приложение должно обеспечить a URLSession:task:needNewBodyStream:
метод делегата обеспечить новый поток организации в случае ошибки аутентификации. Этот метод описан далее в Загрузке Содержания Организации Используя Поток.
Задача загрузки ведет себя точно так же, как задача данных за исключением пути, которым данные возвращаются к Вашему приложению.
Обработка аутентификации и пользовательской проверки цепочки TLS
Если удаленный сервер возвращает код состояния, указывающий, что аутентификация требуется и если та аутентификация требует проблемы уровня соединения (такой как клиентский сертификат SSL), NSURLSession
вызывает метод делегата запроса аутентификации.
Для проблем сеансового уровня —
NSURLAuthenticationMethodNTLM
,NSURLAuthenticationMethodNegotiate
,NSURLAuthenticationMethodClientCertificate
, илиNSURLAuthenticationMethodServerTrust
—NSURLSession
вызовы объектов делегат сеансаURLSession:didReceiveChallenge:completionHandler:
метод. Если Ваше приложение не обеспечивает метод делегата сеанса,NSURLSession
вызовы объектов делегат задачиURLSession:task:didReceiveChallenge:completionHandler:
метод для обработки проблемы.Для проблем несеансового уровня (все другие),
NSURLSession
вызовы объектов делегат сеансаURLSession:task:didReceiveChallenge:completionHandler:
метод для обработки проблемы. Если Ваше приложение предоставляет делегату сеанса, и необходимо обработать аутентификацию, то необходимо или обработать аутентификацию на уровне задачи или обеспечить обработчик уровня задачи, вызывающий обработчик на сеанс явно. Делегат сеансаURLSession:didReceiveChallenge:completionHandler:
метод не вызывают для проблем несеансового уровня.
Когда аутентификация перестала работать для задачи, имеющей организацию загрузки на основе потоков, задача не может обязательно перемотаться и повторное использование тот поток безопасно. Вместо этого NSURLSession
вызовы объектов делегат URLSession:task:needNewBodyStream:
метод делегата получить новое NSInputStream
объект, предоставляющий данные организации для нового запроса. (Объект сеанса не выполняет этот вызов, если организации загрузки задачи предоставлены от файла или NSData
объект.)
Для получения дополнительной информации о записи метода делегата аутентификации для NSURLSession
, считайте Запросы аутентификации и Проверку Цепочки TLS.
Обработка Фонового Действия iOS
Если Вы используете NSURLSession
когда загрузка завершается, в iOS автоматически повторно запускается Ваше приложение. Ваше приложение application:handleEventsForBackgroundURLSession:completionHandler:
когда сеанс вызывает Вашего делегата сеанса, метод делегата приложения ответственен за воссоздание надлежащего сеанса, хранение обработчика завершения, и вызов того обработчика URLSessionDidFinishEventsForBackgroundURLSession:
метод.
Перечисление 1-8 и Перечисление 1-9 показывают примеры их сеанс и методы делегата приложения, соответственно.
Методы делегата Сеанса перечисления 1-8 для фоновых загрузок iOS
#if TARGET_OS_IPHONE |
-(void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session |
{ |
NSLog(@"Background URL session %@ finished events.\n", session); |
if (session.configuration.identifier) |
[self callCompletionHandlerForSession: session.configuration.identifier]; |
} |
- (void) addCompletionHandler: (CompletionHandlerType) handler forSession: (NSString *)identifier |
{ |
if ([ self.completionHandlerDictionary objectForKey: identifier]) { |
NSLog(@"Error: Got multiple handlers for a single session identifier. This should not happen.\n"); |
} |
[ self.completionHandlerDictionary setObject:handler forKey: identifier]; |
} |
- (void) callCompletionHandlerForSession: (NSString *)identifier |
{ |
CompletionHandlerType handler = [self.completionHandlerDictionary objectForKey: identifier]; |
if (handler) { |
[self.completionHandlerDictionary removeObjectForKey: identifier]; |
NSLog(@"Calling completion handler.\n"); |
handler(); |
} |
} |
#endif |
Методы делегата Приложения перечисления 1-9 для фоновых загрузок iOS
- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler |
{ |
NSURLSessionConfiguration *backgroundConfigObject = [NSURLSessionConfiguration backgroundSessionConfiguration: identifier]; |
NSURLSession *backgroundSession = [NSURLSession sessionWithConfiguration: backgroundConfigObject delegate: self.mySessionDelegate delegateQueue: [NSOperationQueue mainQueue]]; |
NSLog(@"Rejoining session %@\n", identifier); |
[ self.mySessionDelegate addCompletionHandler: completionHandler forSession: identifier]; |
} |