NSURLConnection didReceiveData未被调用

F.X*_*.X. 6 objective-c nsurlconnection ios

我已经阅读了大量的消息再次说同样的事情:当你使用NSURLConnection时,不会调用委托方法.我理解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
});
Run Code Online (Sandbox Code Playgroud)

...代理方法的代码在这里:

- (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];
}
Run Code Online (Sandbox Code Playgroud)

这里没有很多错误检查,但我确定了一些事情:

  • 无论发生什么,didReceiveData不会被调用,所以我没有得到任何数据
  • ...但是数据被转移(我使用了检查tcpdump)
  • ...并成功调用其他方法.
  • 如果我使用NSURLConnectionDownloadDelegate而不是NSURLConnectionDataDelegate,一切正常但我无法保留下载的文件(这是一个已知的错误)
  • 在错误的内存管理完成之前,请求不会被释放
  • 如果我在互联网上的某个地方使用标准HTML页面作为我的URL,则没有任何变化
  • 请求从主队列中启动

我不想使用第三方库,因为最终,这些请求将被包含在我自己的库中,并且我想最小化依赖性.如果必须的话,我会CFNetwork直接使用,但是你知道什么会是一个巨大的痛苦.

如果您有任何想法,那将会有很大帮助.谢谢!

Mik*_*keQ 13

我遇到了同样的问题.非常讨厌,但似乎如果你实现这个方法:

- (void)connectionDidFinishDownloading:(NSURLConnection *)connection destinationURL:(NSURL *)destinationURL
Run Code Online (Sandbox Code Playgroud)

然后connection:didReceiveData:永远不会被召唤.你必须使用connectionDidFinishLoading:...是的,文档说它已被弃用,但我认为这只是因为这个方法从而NSURLConnectionDelegate进入NSURLConnectionDataDelegate.


Jes*_*mpo 2

我喜欢使用 sendAsynchronousRequest 方法。连接期间的信息较少,但代码干净得多。

    [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);
    }];
Run Code Online (Sandbox Code Playgroud)

来自苹果:

默认情况下,连接创建时会以默认模式调度在当前线程上。如果使用 initWithRequest:delegate:startImmediately: 方法创建连接并为 startImmediately 参数提供 NO,则可以在使用 start 方法启动连接之前将连接安排在不同的运行循环或模式上。您可以在多个运行循环和模式上安排连接,或者在多个模式下的同一运行循环上安排连接。

除非有理由在 [NSRunLoop currentRunLoop] 中显式运行它,否则您可以删除这两行:

[connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
[connection start];
Run Code Online (Sandbox Code Playgroud)

或者将模式更改为 NSDefaultRunLoopMode