Я создаю приложение для iPhone, которое объединяет данные из нескольких различных источников данных и отображает их вместе в одной таблице.Для каждого источника данных я создал класс (WeatherProvider
, TwitterProvider
), который обрабатывает подключение к источнику данных, загружает данные и сохраняет их в объекте.
У меня есть другой класс 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];
}