Используя NSURLConnection

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

Создание соединения

NSURLConnection класс поддерживает три способа получить содержание URL: синхронно, асинхронно с помощью блока обработчика завершения, и асинхронно с помощью пользовательского объекта делегата.

Получать содержание URL синхронно: В коде, работающем исключительно на фоновом потоке, можно вызвать sendSynchronousRequest:returningResponse:error: выполнять Запрос HTTP. Этот вызов возвращается, когда запрос завершается, или ошибка происходит. Для получения дополнительной информации посмотрите Данные Получения Синхронно.

Получать содержание URL с помощью блока обработчика завершения: Если Вы не должны контролировать состояние запроса, но просто должны выполнить некоторую работу, когда данные были полностью получены, можно вызвать sendAsynchronousRequest:queue:completionHandler:, передача блока для обработки результатов. Для получения дополнительной информации посмотрите, что Данные Получения Используют Блок Обработчика Завершения.

Получать содержание URL с помощью объекта делегата: Создайте класс делегата, реализующий, по крайней мере, следующие методы делегата: connection:didReceiveResponse:, connection:didReceiveData:, connection:didFailWithError:, и connectionDidFinishLoading:. Поддерживаемые методы делегата определяются в NSURLConnectionDelegate, NSURLConnectionDownloadDelegate, и NSURLConnectionDataDelegate протоколы.

Пример в Перечислении 2-1 инициирует соединение для URL. Этот отрывок начинается путем создания NSURLRequest экземпляр для URL, указывая политику доступа кэша и интервал тайм-аута для соединения. Это тогда создает NSURLConnection экземпляр, указывая запрос и делегата. Если NSURLConnection не может создать соединение для запроса, initWithRequest:delegate: возвраты nil. Отрывок также создает экземпляр NSMutableData хранить данные, которые инкрементно предоставлены для делегата.

Перечисление 2-1  , Создающее использование соединения NSURLConnection

// Create the request.
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.apple.com/"]
                        cachePolicy:NSURLRequestUseProtocolCachePolicy
                    timeoutInterval:60.0];
 
// Create the NSMutableData to hold the received data.
// receivedData is an instance variable declared elsewhere.
receivedData = [NSMutableData dataWithCapacity: 0];
 
// create the connection with the request
// and start loading the data
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if (!theConnection) {
    // Release the receivedData object.
    receivedData = nil;
 
    // Inform the user that the connection failed.
}

Передача запускается непосредственно после получения initWithRequest:delegate: сообщение. Это может быть отменено любое время, прежде чем делегат получит a connectionDidFinishLoading: или connection:didFailWithError: сообщение путем отправки соединения a cancel сообщение.

Когда сервер предоставил достаточные данные для создания NSURLResponse объект, делегат получает a connection:didReceiveResponse: сообщение. Метод делегата может исследовать предоставленное NSURLResponse возразите и решите, что ожидаемая длина содержания данных, типа MIME, предложила имя файла и другие метаданные, предоставленные сервером.

Вы должны быть подготовлены к Вашему делегату получить connection:didReceiveResponse: обменивайтесь сообщениями многократно для единственного соединения; если ответ находится в многослойном кодировании MIME, это может произойти. Каждый раз делегат получает connection:didReceiveResponse: сообщение, это должно сбросить любую индикацию прогресса и отбросить все ранее полученные данные (кроме случая многослойных ответов). Реализация в качестве примера в Перечислении 2-2 просто сбрасывает длину полученных данных к 0 каждым разам, когда это вызывают.

  Пример перечисления 2-2 connection:didReceiveResponse: реализация

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    // This method is called when the server has determined that it
    // has enough information to create the NSURLResponse object.
 
    // It can be called multiple times, for example in the case of a
    // redirect, so each time we reset the data.
 
    // receivedData is an instance variable declared elsewhere.
    [receivedData setLength:0];
}

Делегат периодически отправляется connection:didReceiveData: сообщения как данные получены. Реализация делегата ответственна за то, что хранила недавно полученные данные. В реализации в качестве примера в Перечислении 2-3 новые данные добавляются к объекту NSMutableData, создаваемому в Перечислении 2-1.

  Пример перечисления 2-3 connection:didReceiveData: реализация

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    // Append the new data to receivedData.
    // receivedData is an instance variable declared elsewhere.
    [receivedData appendData:data];
}

Можно также использовать connection:didReceiveData: метод для обеспечения индикации относительно прогресса соединения пользователю. Чтобы сделать это, необходимо сначала получить ожидаемую длину содержания путем вызова expectedContentLength метод на ответе URL возражает в Вашем connection:didReceiveResponse: метод делегата. Если сервер не предоставляет информацию длины, expectedContentLength возвраты NSURLResponseUnknownLength.

Если ошибка происходит во время передачи, делегат получает a connection:didFailWithError: сообщение. NSError объект передал, поскольку параметр указывает подробные данные ошибки. Это также обеспечивает URL запроса, переставшего работать в пользовательском информационном словаре с помощью ключа NSURLErrorFailingURLStringErrorKey.

После того, как делегат получает a connection:didFailWithError: сообщение, это не получает дальнейших сообщений делегата для указанного соединения.

Пример в Перечислении 2-4 выпускает соединение, а также любые полученные данные, и регистрирует ошибку.

  Пример перечисления 2-4 connection:didFailWithError: реализация

- (void)connection:(NSURLConnection *)connection
  didFailWithError:(NSError *)error
{
    // Release the connection and the data object
    // by setting the properties (declared elsewhere)
    // to nil.  Note that a real-world app usually
    // requires the delegate to manage more than one
    // connection at a time, so these lines would
    // typically be replaced by code to iterate through
    // whatever data structures you are using.
    theConnection = nil;
    receivedData = nil;
 
    // inform the user
    NSLog(@"Connection failed! Error - %@ %@",
          [error localizedDescription],
          [[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}

Наконец, если соединение преуспевает в том, чтобы получить запрос, делегат получает connectionDidFinishLoading: сообщение. Делегат не получает дальнейших сообщений для соединения, и приложение может выпустить NSURLConnection объект.

Реализация в качестве примера в Перечислении 2-5 регистрирует длину полученных данных и выпускает и объект соединения и полученные данные.

  Пример перечисления 2-5 connectionDidFinishLoading: реализация

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    // do something with the data
    // receivedData is declared as a property elsewhere
    NSLog(@"Succeeded! Received %d bytes of data",[receivedData length]);
 
    // Release the connection and the data object
    // by setting the properties (declared elsewhere)
    // to nil.  Note that a real-world app usually
    // requires the delegate to manage more than one
    // connection at a time, so these lines would
    // typically be replaced by code to iterate through
    // whatever data structures you are using.
    theConnection = nil;
    receivedData = nil;
}

Этот пример представляет самую простую реализацию клиента, использующего NSURLConnection. Дополнительные методы делегата предоставляют возможность для настройки обработки перенаправлений сервера, запросов авторизации и кэширования ответа.

Подача с запросом POST

Можно сделать HTTP или HTTPS запросом POST почти тем же способом, которым Вы сделали бы любой другой URL-запрос (описанным в Примере Аутентификации). Основное различие - то, что необходимо сначала сконфигурировать NSMutableURLRequest объект Вы обеспечиваете для initWithRequest:delegate: метод.

Также необходимо создать данные организации. Можно сделать это одним из трех способов:

При загрузке данных на совместимый сервер загрузочная система URL также поддерживает 100 (Продолжайте) Код состояния HTTP, позволяющий загрузке продолжаться, где он кончил в случае ошибки аутентификации или другого отказа. Для включения поддержки продолжения загрузки установите Expect: заголовок по запросу возражает против 100-continue.

Перечисление 6-1 показывает, как сконфигурировать NSMutableURLRequest объект для запроса POST.

Перечисление 2-6  , конфигурирующее NSMutableRequest объект для запроса POST

// In body data for the 'application/x-www-form-urlencoded' content type,
// form fields are separated by an ampersand. Note the absence of a
// leading ampersand.
NSString *bodyData = @"name=Jane+Doe&address=123+Main+St";
 
NSMutableURLRequest *postRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://www.apple.com"]];
 
// Set the request's content type to application/x-www-form-urlencoded
[postRequest setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
 
// Designate the request a POST request and specify its body data
[postRequest setHTTPMethod:@"POST"];
[postRequest setHTTPBody:[NSData dataWithBytes:[bodyData UTF8String] length:strlen([bodyData UTF8String])]];
 
// Initialize the NSURLConnection and proceed as described in
// Retrieving the Contents of a URL

Для указания различного типа контента для запроса используйте setValue:forHTTPHeaderField: метод. Если Вы делаете, удостоверьтесь, что Ваши данные организации должным образом отформатированы для того типа контента.

Для получения оценки прогресса для запроса POST реализуйте a connection:didSendBodyData:totalBytesWritten:totalBytesExpectedToWrite: метод в делегате соединения. Обратите внимание на то, что это не точное измерение прогресса загрузки, потому что связь может прерваться, или соединение может встретиться с запросом аутентификации.

Получение данных Используя блок обработчика завершения

NSURLConnection класс предоставляет поддержку для получения содержания ресурса, представленного NSURLRequest объект асинхронным способом и вызовом блока, когда результаты возвращаются или когда происходят ошибка или тайм-аут. Чтобы сделать это, вызовите метод класса sendAsynchronousRequest:queue:completionHandler:, обеспечивая объект запроса, блок обработчика завершения, и NSOperation очередь, на которой должен работать тот блок. Когда запрос завершается, или ошибка происходит, вызовы загрузочной системы URL, блокирующие с данными результата или информацией об ошибке.

Если запрос успешно выполняется, содержание запроса передается блоку обработчика обратного вызова как NSData возразите и NSURLResponse объект для запроса. Если NSURLConnection неспособно получить URL, NSError объект передается как третий параметр.

Получение данных синхронно

NSURLConnection класс предоставляет поддержку для получения содержания ресурса, представленного NSURLRequest объект синхронным способом с помощью метода класса sendSynchronousRequest:returningResponse:error:. Используя этот метод не рекомендуется, потому что он имеет серьезные ограничения:

Если запрос успешно выполняется, содержание запроса возвращается как NSData возразите и NSURLResponse объект для запроса возвращается ссылкой. Если NSURLConnection неспособно получить URL, возвраты метода nil и любой доступный NSError экземпляр ссылкой в надлежащем параметре.

Если запрос требует, чтобы аутентификация сделала соединение, допустимые учетные данные должны уже быть доступными в NSURLCredentialStorage возразите или должен быть предоставлен как часть требуемого URL. Если учетные данные не доступны или не удаются аутентифицировать, загрузочная система URL отвечает путем отправки NSURLProtocol подкласс, обрабатывающий соединение a continueWithoutCredentialForAuthenticationChallenge: сообщение.

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