При использовании NSURLConnection данные не возвращаются асинхронно - PullRequest
7 голосов
/ 26 апреля 2009

У меня чертовски много времени с чем-то, что кажется
просто, но я не могу начать работать. Я строю
Приложение для iPhone, которое получает данные с веб-хостинга. Я пытаюсь
установить асинхронное соединение с хостом, так как я хочу сохранить
устройство освобождено во время соединения. (sendSynchronousRequest зависает
телефон, пока запрос не будет выполнен.) Вот мой код подключения:

//temp url to see if data is returned:
NSURL *theURL = [NSURL URLWithString:@"http://www.theappleblog.com/feed"];

NSURLRequest *dataRequest = [NSURLRequest requestWithURL:theURL
             cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
             timeoutInterval:60];

/* establish the connection */  
theConnection = [[NSURLConnection alloc]
                 initWithRequest:dataRequest
                        delegate:self
                startImmediately:YES];

if (theConnection == nil) { 
    NSLog(@"Connection Failure!");
    self.urlData = nil; 
} else {
    self.urlData = [[NSMutableData data] retain];   
}

У меня настроены все соответствующие методы делегата:

-(void)connection:(NSURLConnection *)connection
       didReceiveResponse:(NSURLResponse*)response
{
    [urlData setLength:0];
    UIApplication *application = [UIApplication sharedApplication];
    application.networkActivityIndicatorVisible = YES;
    NSLog(@"Received Response!");
}

-(void)connection:(NSURLConnection *)connection
       didReceiveData:(NSData*)incrementalData
{
    [self.urlData appendData:incrementalData];

    NSNumber *resourceLength = [NSNumber
              numberWithUnsignedInteger:[self.urlData length]];
    NSLog(@"resourceData length: %d", [resourceLength intValue]);
    NSLog(@"filesize: %d", self.urlDataSize);
    NSLog(@"float filesize: %f", [self.urlDataSize floatValue]);
}

-(void)connectionDidFinishLoading:(NSURLConnection*)connection
{
    NSLog(@"Connection finished loading\n");
    NSLog(@"Succeeded! Received %d bytes of data",[urlData length]);
    _isFinished = YES;
    UIApplication *application = [UIApplication sharedApplication];
    application.networkActivityIndicatorVisible = NO;
}

- (void)connection:(NSURLConnection *)connection
        didFailWithError:(NSError *)error
{
    NSLog(@"Error: %@",[error localizedDescription]);
}

Как видите, я получил кучу сообщений журнала, потому что хотел
чтобы увидеть, если что-нибудь проходил вообще. Тест моего соединения
возвращается как TRUE, но данные никогда не загружаются. Как я уже сказал, я уверен
Я должен делать (или не делать) что-то действительно глупо. Но что?
Любая помощь будет наиболее ценной.

Спасибо, Лоуренс

Ответы [ 9 ]

2 голосов
/ 17 июня 2009

Проблема заключалась в том, что я продолжал выполнение программы и не останавливался, чтобы завершить загрузку соединения. Спасибо за все предложения.

1 голос
/ 13 мая 2009

Несколько предложений:

  • В вашем первом фрагменте вместо theConnection попробуйте присвоить self.theConnection, чтобы убедиться, что методы доступа к свойствам вызываются. В разных местах вы также обмениваетесь self.urlData и urlData. Возможно, вы захотите привести их в соответствие, пройдя через self.

  • Возможно, вы захотите также сделать свойство dataRequest и пройти через self, чтобы убедиться, что оно сохраняется.

  • self.urlData = [[NSMutableData data] retain]; - вам не нужно это дополнительное удержание. Прохождение self сделает это за вас. Из-за дополнительного удержания объект будет слипаться и протекать, даже когда все будет сделано.

  • В связанной заметке, в ваших NSLogs убедитесь, что вы распечатали счетчик хранения для каждого объекта. Кроме того, вы можете захотеть иметь общую процедуру очистки, чтобы освободить эти структуры (или установить self.foo = nil), поэтому в любой момент, если она прервется, вы можете вызвать процедуру, чтобы очистить вещи.

  • Получите копию Charles или WireShark (или запустите tcpdump в консоли) и наблюдайте за сетевым трафиком. Это поможет точно определить, на каком этапе потока происходит сбой.

0 голосов
/ 01 мая 2009

Отзывчиво ли приложение? Runloop работает? Что делает приложение после запуска запроса - возвращается ли оно из своего обработчика событий обратно в цикл выполнения? (Если нет, вы никогда не получите ни одного из ваших обратных вызовов, потому что они доставляются через runloop.)

0 голосов
/ 13 мая 2009

NSURLConnection предназначен для работы с любым типом протокола, а не только с HTTP. Это означает, что connection: didFail: withError вызывается для ошибок connection , но не для ошибок protocol . Вы не проверяете наличие ошибок протокола - вы должны отлавливать их при подключении: didReceiveResponse :. Хитрость в том, что переданный объект ответа на самом деле является объектом NSHTTPURLResponse. Если вы проверите код статуса ответа, держу пари, что вы получаете ошибку HTTP, такую ​​как 404 или сервер 500.

0 голосов
/ 27 апреля 2009

Вы говорите, что этот код работает нормально, используя асинхронный метод? Тестируя этот URL, он перенаправляет на другой, что, если вы реализуете методы делегирования перенаправления? Что если вы попробуете несколько разных URL?

0 голосов
/ 27 апреля 2009

Это не дает прямого ответа на ваш вопрос, но вы можете рассмотреть возможность поиска библиотеки ASIHTTPRequest Бена Копси, которая охватывает классы CFNetwork и включает в себя асинхронный многопоточный код запроса, который занимает много времени. работать из этого правильно.

0 голосов
/ 27 апреля 2009

Трудно сосредоточиться на чем-либо, поскольку из вашего вопроса непонятно, какой из операторов NSLog выполняется. Пожалуйста, будьте немного яснее о результатах, которые вы получаете.

На первый взгляд, единственная вещь, которая выглядит как потенциальная проблема, это то, что у вас есть состояние гонки, когда вы устанавливаете соединение. Если сеть работает особенно быстро, существует небольшая, но ненулевая вероятность того, что -connection: didReceiveData: будет вызвано до того, как будет выделен self.urlData. Я бы предложил выделить urlData либо перед установлением соединения, либо в -connection: didReceiveResponse: чтобы предотвратить это.

Если это не помогает, вам нужна дополнительная информация.

0 голосов
/ 27 апреля 2009

Ничего явно плохого там нет. У меня есть код, который по существу такой же и работает нормально. Единственные различия, которые я вижу:

  • Я использую NSURLRequestUseProtocolCachePolicy вместо NSURLRequestReloadIgnoringLocalCacheData

  • Я использую соединение = [[NSURLConnection alloc] initWithRequest: делегатRequest: self]; вместо указания startImmediately: ДА (так как это по умолчанию)

Было бы полезно узнать, какие из ваших методов-делегатов, если таковые имеются, вызываются. По крайней мере, вы должны получить хотя бы один или другой из вызываемых connectionDidFinishLoading или connectionDidFail. Если нет, то, возможно, что-то не так с настройкой вашего делегата - вы АБСОЛЮТНО уверены, что сигнатуры метода делегата верны и что вы передаете правильный элемент в качестве делегата?

0 голосов
/ 27 апреля 2009

Начальная мысль - правильно ли сохраняется объект, у которого весь этот код? Может быть, оно освобождается, и, следовательно, освобождает соединение ...

В противном случае вы должны хотя бы увидеть ответ.

...