问题描述
我正在构建一个 iPhone 应用程序,该应用程序聚合来自多个不同数据源的数据并将它们一起显示在一个表中.对于每个数据源,我都创建了一个类(WeatherProvider
、TwitterProvider
)来处理连接到数据源、下载数据并将其存储在一个对象中.
I'm building an iPhone app that aggregates data from several different data sources and displays them together in a single table. For each data source, I've created a class (WeatherProvider
, TwitterProvider
) that handles connecting to the datasource, download the data and storing it in an object.
我有另一个类 ConnectionManager
,它实例化并调用两个提供程序类中的每一个,并将结果合并到一个显示在表中的 NSArray 中.
I have another class ConnectionManager
, that instantiates and calls each of the two provider classes, and merges the results into a single NSArray which is displayed in the table.
当我运行只调用 WeatherProvider 或 TwitterProvider 的程序时,它运行良好.我可以一次又一次地调用这些对象中的每一个,以使它们保持最新而不会出现问题.我也可以毫无问题地调用 TwitterProvider 和 WeatherProvider.
When I run the program calling just the WeatherProvider or just the TwitterProvider, it works perfectly. I can call each of those objects again and again to keep them up-to-date without a problem. I can also call TwitterProvider and then WeatherProvider without a problem.
但是,如果我先调用 WeatherProvider,然后调用 TwitterProvider,则 TwitterProvider 会在我调用时挂起:[[NSURLConnection alloc] initWithRequest:request delegate:self];
.
However, if I call WeatherProvider then TwitterProvider, the TwitterProvider hangs just as I call: [[NSURLConnection alloc] initWithRequest:request delegate:self];
.
其他要点:- 在我调用 WeatherProvider 和 TwitterProvider 之间的时间间隔似乎无关紧要,TwitterProvider 仍然挂起.- 在 WeatherProvider 中,我使用 NSXMLParser 和 NSAutoreleasePool 来解析 WeatherProvider 的输出.- ConnectionManager 在应用程序启动时创建 WeatherProvider 和 TwitterProvider 的实例,并在用户请求数据刷新时重用这些实例.- 我在连接活动监视器的情况下运行该应用程序,它验证该应用程序基本上只是挂起.似乎没有发生 CPU 使用率、额外的内存分配或网络活动.
Other points: - it doesn't seem to matter how long between when I call WeatherProvider and TwitterProvider, TwitterProvider still hangs. - in WeatherProvider, I'm using NSXMLParser with NSAutoreleasePool to parse the output from the WeatherProvider. - ConnectionManager creates an instance of WeatherProvider and TwitterProvider when the application is started, and reuses those instances when the user requests a data refresh. - I ran the app with the activity monitor connected and it verifies that the app is basically just hanging. No CPU usage, or additional memory allocations or network activity seems to be happening.
有一堆代码分布在几个文件中,所以我尝试在此处包含相关位(据我所知!).我非常感谢您提供的任何帮助,即使只是额外的调试方法.
There's a bunch of code spread across a couple files, so I've tried to include the relevant bits (as far as I can tell!) here. I very much appreciate any help you can provide, even if it is just additional approaches to debugging.
天气提供者
-(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];
}
推荐答案
我能够通过删除用于 NSXMLParser 的 WeatherUpdater 中的线程来解决此问题.我从 Apple 的 SiesmicXML 示例应用程序中删除"了该代码.
I was able to fix this by removing the threading in WeatherUpdater that was being used for the NSXMLParser. I had 'barrowed' that code from Apple's SiesmicXML sample app.
这篇关于NSURLConnection 在第二次调用时挂起的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!