NSURLConnection,NSOperation和NSRunLoop对线程的混淆

时间:2014-07-22 18:33:30

标签: ios multithreading nsurlconnection nsoperation nsrunloop

我在使用NSURLConnection和NSRunLoop时感到困惑。 我正在尝试使用NSURLConnection下载一个大文件,但它不能正常工作(甚至没有调用单个委托方法)。

    NSURL *url = [NSURL URLWithString:@"http://127.0.0.1:8080/"];
    NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] initWithURL:url] autorelease];
    [request setHTTPBody:[@"Request Body Data" dataUsingEncoding:NSUTF8StringEncoding]];
    [request setHTTPMethod:@"POST"];

在主线程上运行。

仅适用于小尺寸的文件。当我尝试下载18MB文件时,它无效。

  1. 它不适用于大图像文件。

    [NSURLConnection connectionWithRequest:request delegate:self];
    
  2. 它不适用于大型图像文件,尝试使用18MB。

    NSURLConnection *con = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];
    [con setDelegateQueue:[NSOperationQueue currentQueue]];
    [con start];
    
  3. 它不适用于大型图像文件,尝试使用18MB。

    NSURLConnection *con = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];
    [con scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; // Or NSRunLoopCommonModes
    [con start];
    
  4. 它不适用于大型图像文件,尝试使用18MB。

    NSURLConnection *con = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];
    NSRunLoop *loop = [NSRunLoop currentRunLoop];
    [con scheduleInRunLoop:loop forMode:NSRunLoopCommonModes];
    [con start];
    [loop run];
    
  5. 它不适用于大型图像文件,尝试使用18MB。

    NSHTTPURLResponse *res = nil;
    NSError *err = nil;
    NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&res error:&err];
    NSLog(@"Res Code: %d, DataLen: %d", res.statusCode, data.length);
    
  6. 它适用于大图像

    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue currentQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
        NSHTTPURLResponse *res = (NSHTTPURLResponse*)response;
        NSString *imagePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@"/myImage.jpg"];
        NSLog(@"Res Code: %d, DataLen: %d, Path: %@", res.statusCode, data.length, imagePath);
        [data writeToFile:imagePath atomically:YES];
    }];
    
  7. 在NSOperation上运行(我在 NSOperation的子类中尝试了相同的代码,我已经在github上传了代码。请找到下面的链接。)

    1. 没有任何效果(没有调用委托方法。)
    2. 适合所有人。
    3. 它不适合大文件。
    4. 适合所有人。 (它也适用于NSDefaultRunLoopMode模式,其中apple文档说明了“处理除NSConnection对象之外的输入源的模式。”)。
    5. 适合所有人。
    6. 适合所有人。
    7. I just want to understand the basic logic behind NSRunLoop, when we use it with NSURLConnection object. How NSRunLoop works behind the scene? How does it work with NSURLConnections? What happens when we call any asynchronous request through NSURLConnection on main thread or any secondary thread (created by NSOperation)?

      Sample Code on GitHub

      我已经阅读了几篇与NSRunLoop相关的博客和苹果文档,但仍然感到困惑,所以我写了一篇关于我的理解的文档。 的 NSRunLoop understanding Doc.

      非常感谢提前!

1 个答案:

答案 0 :(得分:0)

混乱是好的,这是一个信号,你缺少答案,甚至可能是问题。据我所知,这里缺少的问题是:我们真的需要NSOperation和NSRunLoop吗? NSURLConnection sendAsynchronousRequest:和sendSynchronousRequest:已经在runloops中调度操作 - 添加NSOperation和NSRunLoop没有帮助,可能会阻碍。 因此,请专注于您真正需要的方法(sendAsynchronousRequest:或sendSynchronousRequest :)并充分利用它们。拿这个代码:

[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue currentQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
    NSHTTPURLResponse *res = (NSHTTPURLResponse*)response;
    NSString *imagePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@"/myImage.jpg"];
    NSLog(@"Res Code: %d, DataLen: %d, Path: %@", res.statusCode, data.length, imagePath);
    [data writeToFile:imagePath atomically:YES];
}];

你确实将NSURLResponse转换为NSHTTPURLResponse,可能是为了读出状态代码,而是你继续前进并将数据对象写入文件。如果状态代码不是200,则没有有效的数据对象要写入文件。状态代码可能是206,在这种情况下,您需要将传入的数据附加到现有文件,或者如果它不存在则创建一个并存储对它的引用,等等。