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"];

Работает на главной теме.

Работает только для небольшого размера файла. Он не работал, когда я пытаюсь загрузить файл размером 18 МБ.

  1. Он не работал для больших файлов изображений.

    [NSURLConnection connectionWithRequest:request delegate:self];
    
  2. Он не работал для большого файла изображения, пробовал с 18 МБ.

    NSURLConnection *con = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];
    [con setDelegateQueue:[NSOperationQueue currentQueue]];
    [con start];
    
  3. Он не работал для большого файла изображения, пробовал с 18 МБ.

    NSURLConnection *con = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];
    [con scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; // Or NSRunLoopCommonModes
    [con start];
    
  4. Он не работал для большого файла изображения, пробовал с 18 МБ.

    NSURLConnection *con = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];
    NSRunLoop *loop = [NSRunLoop currentRunLoop];
    [con scheduleInRunLoop:loop forMode:NSRunLoopCommonModes];
    [con start];
    [loop run];
    
  5. Он не работал для большого файла изображения, пробовал с 18 МБ.

    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];
    }];
    

Запуск в NSOperation (я попытался сделать такой же код выше в подклассе NSOperation, я загрузил код на github. См. Ссылку ниже.)

  1. Ничего не работает (никто из метода делегата не вызван.)
  2. Он РАБОТАЛ для всех.
  3. Он не работал для большого файла.
  4. Он РАБОТАЛ для всех. (Он также работал в режиме NSDefaultRunLoopMode, где в документе apple говорится: “Режим работы с источниками входных данных, отличными от объектов NSConnection”).
  5. Он РАБОТАЛ для всех.
  6. Он РАБОТАЛ для всех.

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)?

Пример кода на GitHub

Я прочитал несколько блогов и документов Apple, связанных с NSRunLoop, но все еще смущен, поэтому я написал документ о своем понимании о том же. NSRunLoop понимает Док.

Спасибо заранее!

Ответ №1

Смятение – это хорошо, это сигнал, что вам не хватает ответов и, возможно, даже вопросов. Насколько я вижу, недостающий вопрос здесь: действительно ли нам нужна 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, и в этом случае вам нужно будет добавить входящие данные в уже существующий файл или создать его, если он не существует, и сохранить ссылку на него и т.д.

Оцените статью
TechArks.Ru
Добавить комментарий