2011-01-15 2 views
0

Я создаю приложение iPhone, которое объединяет данные из нескольких разных источников данных и отображает их вместе в одной таблице. Для каждого источника данных я создал класс (WeatherProvider, TwitterProvider), который обрабатывает подключение к источнику данных, загружает данные и сохраняет их в объекте.NSURLConnection Hanging on Second Call

У меня есть другой класс ConnectionManager, который создает и вызывает каждый из двух классов провайдера и объединяет результаты в один NSArray, который отображается в таблице.

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

Однако, если я позвоню WeatherProvider, то TwitterProvider, TwitterProvider зависает так же, как я звоню: [[NSURLConnection alloc] initWithRequest:request delegate:self];.

Другие пункты: - кажется, не имеет значения, как долго между тем, когда я вызываю WeatherProvider и TwitterProvider, TwitterProvider все еще висит. - В WeatherProvider я использую NSXMLParser с NSAutoreleasePool для анализа результатов WeatherProvider. - ConnectionManager создает экземпляр WeatherProvider и TwitterProvider при запуске приложения и повторно использует эти экземпляры, когда пользователь запрашивает обновление данных. - Я запустил приложение с подключенным монитором активности, и он проверяет, что приложение в основном просто висит. Кажется, что использование ЦП или дополнительные выделения памяти или сетевая активность не происходит.

Здесь есть куча кода, распространяемого через пару файлов, поэтому я попытался включить соответствующие биты (насколько я могу судить!) Здесь. Я очень ценю любую помощь, которую вы можете предоставить, даже если это просто дополнительные подходы к отладке.

WeatherProvider

-(void)getCurrentWeather: (NSString*)lat lon:(NSString*)lon lastUpdate:(double)lastUpdate 
{ 
double now = [[NSDate date] timeIntervalSince1970]; 
NSString *noaaApiUrl; 

// don't update if current forecast is < than 1 hour old 
if(now - lastUpdate < 3600) 
{ 
    [[self delegate] weatherUpdaterComplete:1]; 
    return; 
} 

// if we already have a forecast, delete and refill it. 
if(forecast) 
{ 
    [forecast release]; 
    forecast = [[WeatherForecast alloc] init]; 
} 

forecast.clickThroughUrl = [NSString stringWithFormat:@"http://forecast.weather.gov/MapClick.php?lat=%@&lon=%@", 
          lat, lon]; 

noaaApiUrl = [NSString stringWithFormat:@"http://www.weather.gov/forecasts/xml/sample_products/browser_interface/ndfdBrowserClientByDay.php?lat=%@&lon=%@&format=24+hourly", 
      lat, lon]; 

NSURLRequest *noaaUrlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:noaaApiUrl]]; 
[[NSURLConnection alloc] initWithRequest:noaaUrlRequest delegate:self]; 
} 

#pragma mark - 
#pragma mark NSURLConnection delegate methods 

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response 
{ 
    self.noaaData = [NSMutableData data]; 
} 

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

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 
{ 
    self.noaaConnection = nil; 
    [[self delegate] weatherUpdaterError:error]; 
    [connection release]; 
} 

- (void)connectionDidFinishLoading:(NSURLConnection *)connection 
{ 
    // Spawn a thread to fetch the data so UI isn't blocked while we parse 
    // the data. IMPORTANT - don't access UIKit objects on 2ndary threads 
    [NSThread detachNewThreadSelector:@selector(parseNoaaData:) toTarget:self withObject:noaaData]; 

    // the noaaData will be retailed by the thread until parseNoaaData: has finished executing 
    // so, we'll no longer need a reference to it in the main thread. 
    self.noaaData = nil; 
    [connection release]; 
} 

#pragma mark - 
#pragma mark NSXMLParser delegate methods 

- (void)parseNoaaData:(NSData *)data 
{ 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 

    NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data]; 
    [parser setDelegate:self]; 
    [parser parse]; 

    [parser release];   
    [pool release]; 
} 

TwitterProvider

-(void)getLocationTimeline:(NSString*)lat lon:(NSString*)lon lastUpdate:(double)lastUpdate refreshUrl:(NSString*)newUrl 
{ 
    NSString *updateURL; 

    if(tweets.count > 1) 
     [tweets removeAllObjects]; 

    updateURL = [NSString stringWithFormat:@"http://search.twitter.com/search.json?geocode=%@,%@,1mi&rpp=%@&page=1", lat, lon, TWITTER_LOCAL_UPDATES_URL_RESULTS];  

    _serviceResponse = [[NSMutableData data] retain]; 
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:updateURL]]; 
    [[NSURLConnection alloc] initWithRequest:request delegate:self]; 
} 

#pragma mark - 
#pragma mark NSURLConnection delegate methods 

- (void)connectionDidFinishLoading:(NSURLConnection *)connection 
{ 
    NSString *responseString = [[NSString alloc] initWithData:_serviceResponse encoding:NSUTF8StringEncoding]; 

     // parse tweets 

    [responseString release]; 
    [_serviceResponse release]; 
    [connection release]; 

    // tell our delegate that we're done! 
    [[self delegate] twitterUpdaterComplete:tweets.count]; 
} 

- (void)connection:(NSURLConnection *)connection 
didReceiveResponse:(NSURLResponse *)response 
{ 
    [_serviceResponse setLength:0]; 
} 

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

- (void)connection:(NSURLConnection *)connection 
    didFailWithError:(NSError *)error 
{ 
    [connection release]; 

    [[self delegate] twitterUpdaterError:error]; 
} 

ответ

0

я был в состоянии исправить это путем удаления нарезания резьбы в WeatherUpdater, использовавшуюся для NSXMLParser. Я получил код из примера приложения SiesmicXML от Apple.