Используя 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 - кодировать существующую часть данных, как описано в Продолжении Без Учетных данных.
Для загрузки данных файла от диска вызовите
setHTTPBodyStream:
метод для сообщенияNSMutableURLRequest
читать изNSInputStream
и используйте получающиеся данные в качестве содержания организации.Для больших блоков созданных данных вызвать
CFStreamCreateBoundPair
для создания пары потоков затем вызовитеsetHTTPBodyStream:
метод для сообщенияNSMutableURLRequest
использовать один из тех потоков как источник для его содержания организации. Путем записи в другой поток можно отправить данным часть за один раз.В зависимости от того, как Вы обрабатываете вещи на серверной стороне, можно также хотеть к URL - кодируют данные, которые Вы отправляете. (Для получения дополнительной информации посмотрите Продолжение Без Учетных данных.)
При загрузке данных на совместимый сервер загрузочная система 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:
сообщение.
Когда попытка синхронного соединения встречается с перенаправлением сервера, перенаправление всегда соблюдают. Аналогично, данные ответа хранятся в кэше согласно поддержке по умолчанию, предоставленной реализацией протокола.