NSURLConnection didReceiveData не вызывается

Я прочитал множество сообщений, снова и снова говорящих об одном и том же: когда вы используете NSURLConnection, методы делегатаnot called, Я понимаю, что документы Apple являются неполными, и ссылочные устаревшие методы - это позор, но, похоже, я не могу найти решение.

Код для запроса есть:

// Create request
NSURL *urlObj = [NSURL URLWithString:url];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:urlObj cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:30];
[request setValue:@"gzip" forHTTPHeaderField:@"Accept-Encoding"];

if (![NSURLConnection canHandleRequest:request]) {
    NSLog(@"Can't handle request...");
    return;
}

// Start connection
dispatch_async(dispatch_get_main_queue(), ^{
    self.connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES]; // Edited
});

... и код для методов делегата здесь:

- (void) connection:(NSURLConnection *)_connection didReceiveResponse:(NSURLResponse *)response {
    NSLog(@"Receiving response: %@, status %d", [(NSHTTPURLResponse*)response allHeaderFields], [(NSHTTPURLResponse*) response statusCode]);
    self.data = [NSMutableData data];
}

- (void) connection:(NSURLConnection *)_connection didFailWithError:(NSError *)error {
    NSLog(@"Connection failed: %@", error);
    [self _finish];
}

- (void) connection:(NSURLConnection *)_connection didReceiveData:(NSData *)_data {
    [data appendData:_data];
}

- (void)connectionDidFinishDownloading:(NSURLConnection *)_connection destinationURL:(NSURL *) destinationURL {
    NSLog(@"Connection done!");
    [self _finish];
}

Здесь не так много проверок на ошибки, но я удостоверился в нескольких вещах:

Whatever happens, didReceiveData is never called, so I don't get any data ...but the data is transfered (I checked using tcpdump) ...and the other methods are called successfully. If I use the NSURLConnectionDownloadDelegate instead of NSURLConnectionDataDelegate, everything works but I can't get a hold on the downloaded file (this is a known bug) The request is not deallocated before completion by bad memory management Nothing changes if I use a standard HTML page somewhere on the internet as my URL The request is kicked off from the main queue

Я не хочу использовать стороннюю библиотеку, так как, в конечном счете, эти запросы должны быть включены в мою собственную библиотеку, и я хотел бы минимизировать зависимости. Если мне нужно, я буду использоватьCFNetwork напрямую, но это будет огромной болью в том, что вы знаете, что.

Если у вас есть идея, это очень поможет. Спасибо!

 Jesse Gumpo10 июл. 2012 г., 21:35
вы проверили с помощью NSLog () внутри didReceiveData?
 Jesse Gumpo10 июл. 2012 г., 21:42
попробуйте положить в mainRunLoop?
 F.X.10 июл. 2012 г., 21:45
@Dima: попробовал, не получилось ... ИNSURLConnectionDataDelegate является подпротоколомNSURLConnectionDelegateтак что это не будет сильно отличаться ...
 F.X.10 июл. 2012 г., 21:45
@JesseGumpo: вот чтоdispatch_async не так ли? Если я не очень ошибаюсь, в этом случае я прошу прощения ...
 F.X.10 июл. 2012 г., 21:40
Да, NSLogand точки останова, ничего не называется ...

Ответы на вопрос(4)

но кажется, что если вы реализуете этот метод:

- (void)connectionDidFinishDownloading:(NSURLConnection *)connection destinationURL:(NSURL *)destinationURL

затемconnection:didReceiveData: никогда не будет называться. Вы должны использоватьconnectionDidFinishLoading: вместо этого ... Да, документы говорят, что это устарело, но я думаю, что это только потому, что этот метод перешел отNSURLConnectionDelegate вNSURLConnectionDataDelegate.

 25 апр. 2016 г., 16:06
@DanF, очень полезный комплимент. Благодарю.
 11 дек. 2013 г., 05:34
Вы спасли меня! Как неожиданно!
 08 февр. 2015 г., 22:01
Это было именно то, что мне нужно было сделать. Я наивно реализовалNSURLConnectionDelegate, NSURLConnectionDataDelegate, а такжеNSURLConnectionDownloadDelegateдумая, что эти три дадут мне наибольшее количество информации, чтобы я мог передать своему пользователю информацию о ходе загрузки данных, и реализовал методы, которые он предупреждал, в которых я нуждался. Вы не должныNSURLConnectionDownloadDelegate если вы используетеdidReceiveData
 27 авг. 2013 г., 11:57
Спасибо Apple, чтобы вставить непредсказуемое поведение в их SDK ......
 08 мая 2013 г., 08:39
Действительно очень раздражает! 1 ++
Решение Вопроса

инения информации меньше, но код намного чище.

    [NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error){
        if (data){
            //do something with data
        }
        else if (error)
            NSLog(@"%@",error);
    }];

От Apple:

By default, a connection is scheduled on the current thread in the default mode when it is created. If you create a connection with the initWithRequest:delegate:startImmediately: method and provide NO for the startImmediately parameter, you can schedule the connection on a different run loop or mode before starting it with the start method. You can schedule a connection on multiple run loops and modes, or on the same run loop in multiple modes.

Если нет причины явно запустить его в [NSRunLoop currentRunLoop], Вы можете удалить эти две строки:

[connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
[connection start];

или измените режим на NSDefaultRunLoopMode

 10 июл. 2012 г., 21:58
Вы можете сделать: [..initWithRequest :() делегат :()] ИЛИ [..initWithRequest :() делегировать :() startImmediately :()] и включить [..scheduleIn ..]
 F.X.10 июл. 2012 г., 21:57
Вы на самом деле правы, но это ничего не меняет ...; (хотя я отредактировал свой код! Я не уверен, что у меня есть знания помимо базовых, когда дело доходит до выполнения циклов и очередей, поэтому скажите мне, если я "; я не делаю что-то правильно!
 16 мар. 2015 г., 22:58
Это не только решило описанную проблему, но и избавило от утечки, вызванной вызовом методов, которые я использовал.
 F.X.10 июл. 2012 г., 22:03
Из моего понимания (см. Мой код), если вы положитеstartImmediately:YES, он должен работать. Но это не означает, что документы Apple - это беспорядок ...

on the thread это запустило асинхронную операцию загрузки для связанного объекта NSURLConnection. & quot;

Поскольку dispatch_async запустит новый поток, а NSURLConnection не передаст эту другую угрозу обратным вызовам, поэтомуdo not use dispatch_async с NSURLConnection.

Вам не нужно бояться замерзшего пользовательского интерфейса, NSURLConnection обеспечивает только управление асинхронными нагрузками.

Если у вас естьmore files to download, вы можете запустить некоторые соединения в первую очередь, а затем они закончили, используя метод connectionDidFinishLoading: вы можете начинать новые соединения.

int i=0;
for (RetrieveOneDocument *doc in self.documents) {

    if (i<5) {
         [[NSURLConnection alloc] initWithRequest:request delegate:self];
        i++;
    }
}

..

-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    ii++;
    if(ii == 5) {
         [[NSURLConnection alloc] initWithRequest:request delegate:self];
        ii=0;
    }
}
 18 окт. 2015 г., 21:33
dispatch_async не обязательно начинать новую тему (например,dispatch_async(dispatch_get_main_queue(), ^() {}) запускает блок в главном потоке.) Но ваша точка зрения на обратные вызовы, происходящие в текущем потоке, была именно моей проблемой, спасибо!

NSURLRequest был настроен, чтобы иметь-HTTPMethod изHEAD, Довольно сложно сделать это случайно!

Ваш ответ на вопрос