Статьи

Разработка приложений для iPhone — Сеть

Извлечение данных по сети — еще одна важная концепция, с которой нужно ознакомиться в процессе обучения разработке приложений для iOS.

Существует два основных API, которые помогают нам извлекать данные по сети синхронно или асинхронно: NSURLConnection и NSURLSession.

Последний был представлен как часть iOS7 SDK с дополнительными функциями. Есть много библиотек, которые построены на основе этих API.

В этом уроке мы сосредоточимся на этих двух API.

NSURLConnection

Класс NSURLRequest помогает в создании запроса к указанному URL. Он указывает целевой URL и политику кэширования, которая должна быть принята при выполнении запроса URL. Также можно указать тип HTTP-запроса, его поля заголовка и данные публикации. Итак, мы должны создать экземпляр NSURLRequest с необходимой информацией запроса.

Этот объект запроса должен быть передан для инициализации объекта NSURLConnection и запуска запроса.

Делегат соединения также должен быть упомянут.

Асинхронное соединение

Образец запроса GET

NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://samplewebservice.com?x=1&y=2"]];
    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];

Пример почтового запроса с заголовками HTTP

 NSMutableURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://samplewebservice.com"]];
    request.HTTPMethod = @"POST";
    [request setValue:@"text/plain" forHTTPHeaderField:@"Content-Type"];
    NSString *str = @"Post data";
    NSData *postData = [str dataUsingEncoding:NSUTF8StringEncoding];
    request.HTTPBody = postData;
    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];

Пример запроса с политикой кеша

 NSMutableURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://samplewebservice.com"]
                                                    cachePolicy: NSURLRequestReloadIgnoringCacheData
                                                timeoutInterval:20.0];
    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];

После запуска запроса мы должны реализовать методы делегата NSURLConnection для получения данных ответа.

 - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    
  //Declare a NSMutableData variable 'responseData' to hold the response from the server.
  //Initialize or reset the 'responseData' variable here.
    _responseData = [[NSMutableData alloc] init];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    // Append the data that we receive to the 'responseData' variable
    [self.responseData appendData:data];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
  //The response data is fully received.
  //Parsing can be done here
        NSString *strResponse = [[NSString alloc] initWithData:self.responseData encoding:NSUTF8StringEncoding];
    NSLog(@"Response %@",strResponse);
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    // The request has failed due to some error
    NSLog(@"Error %@",[error description]);

}

Существует один простой API, который можно использовать для запуска асинхронного запроса.

 [NSURLConnection sendAsynchronousRequest:request
                                       queue:[NSOperationQueue mainQueue]
                           completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
                               
                           //Parse the data here
                           
                           }];

Вот как мы должны запускать и обрабатывать асинхронное URL-соединение.

Синхронное соединение:

Метод sendSynchronousRequest класса NSURLConnection используется для синхронного вызова сервера.

 NSURLRequest * request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://samplewebservice.com"]];
    NSURLResponse * response = nil;
    NSError * error = nil;
    NSData * responsedata = [NSURLConnection sendSynchronousRequest:request
                                          returningResponse:&response
                                                      error:&error];
    
    if (error == nil)
    {
        // Parse response data here
    }

Ответ и переменные ошибки передаются методу в качестве аргументов. Переменная ответа будет заполнена необработанным ответом, если соединение установлено успешно и ответ получен. Переменная error будет заполнена сведениями об ошибке, если данные ответа не могут быть получены.

Мы должны проверить, имеет ли значение ошибки ноль, прежде чем мы продолжим анализ данных.

NSURLSession

С NSURLSession мы можем настраивать политики кэширования, cookie и учетных данных для каждого сеанса, а не делиться ими между приложениями. Объект NSURLSessionConfiguration помогает в определении этих политик, и объекты NSURLSession создаются с этими объектами конфигурации.

API NSURLSessionConfiguration имеет три параметра конфигурации.

Сеанс по умолчанию: конфигурация, в которой используются глобальные или общие файлы cookie, кэш и хранилища учетных данных. Поведение похож на NSURLConnection.
Ephemeral Session: конфигурация частного сеанса, в которой не сохраняются файлы cookie, кэш и объекты хранения учетных данных Как видно из названия, параметры конфигурации недолговечны и удаляются при аннулировании сеанса.
Фоновый сеанс: аналогичен сеансу по умолчанию, но выгрузка или выгрузка данных может выполняться, даже когда приложение находится в приостановленном состоянии.

Фактические функции загрузки или выгрузки в сеансе выполняются с помощью объектов NSURLSessionTask.

Есть три типа сессионных заданий

Задачи данных: данные отправляются и принимаются в виде объектов NSData
Задачи загрузки: данные получены в виде файла
Задачи загрузки: данные обычно отправляются в виде файла.

Задачи могут быть созданы с обработчиками завершения или делегатами.

При создании сеанса выполните следующие действия

  1. Создайте объект NSURLSessionConfiguration. (По умолчанию / Ephemeral / Background)
  2. Задайте политики кэширования, протокола, файлов cookie или учетных данных и дополнительные параметры конфигурации с помощью созданного объекта конфигурации сеанса.
  3. Создайте объект NSURLSession
  4. Создайте объект NSURLSessionTask (Данные / Загрузить / Загрузить)
  5. Реализуйте обработчик завершения или методы делегата

Пример задачи с обработчиком завершения

Прочитайте встроенные комментарии и попытайтесь понять пример кода, приведенный ниже.

 // Create a default session configuration object
    NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
    //Set policies and other session configuration parameters if required
    [sessionConfig setRequestCachePolicy:NSURLRequestReloadIgnoringCacheData];
    
    //Create a session with the configuration object
    //Set delegate to nil if you are going to use completion handler
    //Set the queue for the completion handlers
    NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:nil delegateQueue:[NSOperationQueue mainQueue]];
    
    //Create a NSURLRequest object with the webservice URL
    NSURLRequest * request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://samplewebservice.com"]];
    //Create a data task object with the session and the request object
    // Implement the completion handler that should be triggered at the end of the request
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        if(error == nil)
        {
            NSString *strResponse = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
            NSLog(@"Response %@",strResponse);
        }
        
    }];
    
    //All the session tasks will be in the suspended state. //Call resume method on the tasks to trigger the request
    [dataTask resume];

Пример задачи с делегатами

Запрос инициации

 NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
    [sessionConfig setRequestCachePolicy:NSURLRequestReloadIgnoringCacheData];
    
    //Specify the custom delegate when creating the session
    NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    NSURL *url = [NSURL URLWithString: @"http://www.example.com/"];
    NSURLSessionDataTask *dataTask = [session dataTaskWithURL: url];
    [dataTask resume];

Методы делегирования задачи данных

 - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
{
    //handle data here
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
    //Called when the data transfer is complete
    //Client side errors are indicated with the error parameter
}

Скачать задачи также есть специальные делегаты

1. Делегат, чтобы указать, что загрузка завершена. Загруженный файл должен быть скопирован в новое место, так как он будет удален из временного места.

 - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
                              didFinishDownloadingToURL:(NSURL *)location;

2. Делегировать, чтобы указать ход загрузки. Индикатор прогресса может обновляться в зависимости от количества загруженных данных.

 - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
                                           didWriteData:(int64_t)bytesWritten
                                      totalBytesWritten:(int64_t)totalBytesWritten
                              totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite;

3. Делегат вызывается, когда загрузка возобновляется

 - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
                                      didResumeAtOffset:(int64_t)fileOffset
                                     expectedTotalBytes:(int64_t)expectedTotalBytes;

Задача загрузки не имеет специальных делегатов, но метод делегата, приведенный ниже, можно использовать для проверки хода загрузки.

 - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
                                didSendBodyData:(int64_t)bytesSent
                                 totalBytesSent:(int64_t)totalBytesSent
                       totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend;

Вывод

Существует намного больше делегатов и сетевых API, которые вы можете изучить самостоятельно. Надеюсь, что эта статья дала некоторое понимание концепций сети.