NSURLConnection sendSynchronousRequest кажется висеть
Этот HTTP-вызов, кажется, висит, и я не понимаю, почему. Строка ведения журнала после вызова никогда не запускается.
Я почти наверняка делаю что-то очень глупое, но если кто-нибудь может понять, что это такое, я был бы благодарен. Насколько я вижу, мой код эквивалентен документам.
Кажется, что не имеет значения, какой URL я использую, и HTTP-запрос никогда не регистрируется сервером (если указано на нем).
NSURLRequest *req = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.google.com/"]];
NSURLResponse *res = nil;
NSError *err = nil;
NSLog(@"About to send req %@",req.URL);
NSData *data = [NSURLConnection sendSynchronousRequest:req returningResponse:&res error:&err];
NSLog(@"this never runs");
Любые идеи?
Обновление
Спасибо всем, кто выложил до сих пор. Все еще видя проблему. Немного подробнее:
- Код тестируется на устройстве
- Другие HTTP-вызовы работают нормально, поэтому, если это проблема сети, это нетривиальная функция
- Код провалился за обычный таймаут. Я знаю, что он висит более 20 минут. Я убил его в тот момент, но я предполагаю, что он будет продолжать висеть.
- В настоящее время я не использую делегат и не планирую, см. ниже.
- В других местах приложения я использую
sendAynchronousRequest
, но в этом случае мне нужно передать возвращаемое значение (и я не в основном потоке), поэтому sendSynchronousRequest
- единственный параметр, который я знаю.
- В случае, если это имеет значение, контекст заключается в том, что я реализую протокол
NSURLCache
, в частности метод cachedResponseForRequest
, для которого требуется вернуть NSCachedURLResponse
Ответы
Ответ 1
Этот код работает в других контекстах, поэтому он ясно, что это происходит, потому что вызов выполняется из метода cachedResponseForRequest
для NSURLCache
. Запуск его в другом месте отлично работает.
Поскольку это предназначалось для включения прокси между вызовами AJAX во встроенном UIWebView
и сервере (для того, чтобы не переписывать код подписи API-кода в JS), я работал вокруг него, используя класс Marcus Westin WebViewProxy, который работает с удовольствием.
Ответ 2
Запустите запрос в фоновом режиме, чтобы он не блокировал основной поток, где происходят обновления пользовательского интерфейса:
dispatch_queue_t myQueue = dispatch_queue_create("myQueue", NULL);
// execute a task on that queue asynchronously
dispatch_async(myQueue, ^{
NSURLRequest *req = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.google.com/"]];
NSURLResponse *res = nil;
NSError *err = nil;
NSLog(@"About to send req %@",req.URL);
NSData *data = [NSURLConnection sendSynchronousRequest:req returningResponse:&res error:&err];
});
Ответ 3
Добавить делегат <NSURLConnectionDataDelegate>
NSURL *url = [[NSURL alloc]initWithString:[NSString stringWithFormat:@"Your string here"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self];
[connection start];//It will start delegates
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[received_data setLength:0];//Set your data to 0 to clear your buffer
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[received_data appendData:data];//Append the download data..
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
//Use your downloaded data here
}
Этот метод более удобен для загрузки данных. Он не будет использовать основной поток, поэтому приложение не будет зависать. Надеюсь, это будет более полезно для вас.
Ответ 4
Когда ваш запрос удастся с ответом, ваш NSLog будет выполняться, потому что метод sendSynchronousRequest работает в основном потоке.
Ответ 5
Его метод a synchronous
- то есть он работает в главном потоке . Поэтому ваше приложение будет зависать - и он будет ждать загрузки данных.
Чтобы предотвратить это: используйте метод sendAsynchronousRequest
. Он будет запускать этот процесс в фоновом потоке и не будет нарушать ваше приложение или просто - не заставит его зависать.
Здесь, как использовать sendAsynchronousRequest
:
NSURL *url = [NSURL URLWithString:@"YOUR_URL_HERE"];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
//the NSData in the completion handler is where your data is downloaded.
}];
Учитывая все обстоятельства, я думаю, что проблема существует из-за вашего объявления делегата. Поэтому объявите <NSURLConnectionDataDelegate>
и объявите объект NSMutableData
: myData
и NSURLConnection
: urlConnection
как свойства. Теперь используйте это:
NSURL *url = [NSURL URLwithString : @"YOUR_URL_HERE"];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
*urlConnection = [NSURLConnection connectionWithRequest:urlRequest delegate:self];
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[myData setLength:0];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[myData appendData:data];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
//You can use the complete downloaded data - NSMutableData here.
}