后续 NSURLConnections 不触发委托方法
我已经到处寻找这个问题的答案,并且看到了很多类似的问题,但解决方案似乎并不适合我的情况。我对 iOS 开发非常陌生,因此我们将不胜感激。
当前的应用程序希望根据其网站生成的 XML 提要来显示城市中发生的事件。我将事件存储在 plist 中,并在应用程序加载时显式检查新事件。当前流程如下:
- 应用程序启动并创建 NSURLConnection 以检查服务器的时间戳并下载它。
- 检查新下载的时间戳与本地时间戳是否更大。如果是,它会重写包含 plist 的文件并发出需要新事件的通知。
这是第二个 NSURLConnection 似乎没有触发的地方。回调方法本身会触发,但委托方法似乎不会在之后触发。
奇怪的是,如果我同时调用两个连接,而不是一个连接作为另一个连接的结果,它们都会触发并调用委托方法。
以下是一些类的代码,为了清晰起见,删除了一些内容:
应用程序委托:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Set up analytics account
// Set the tab bar controller as the window's root view controller and display.
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
//Set up listeners for event handling
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(timeStampResponse:) name:@"TimeStampResponse" object:nil];
//Set app loading screen
//Create new OperationQueue, set ActivityIndicator and run TimeStamp Check
parseQueue = [NSOperationQueue new];
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
[self timeStampCheck];
return YES;
}
-(void)timeStampCheck {
NSLog(@"Time Stamp Check, Creating Connection");
NSURLRequest *timeStampURLRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:kTimeStampURL]];
self.timeStampConnection = [[NSURLConnectionWithTag alloc] initWithRequest:timeStampURLRequest delegate:self startImmediately:YES tag:1];
}
-(void)newEventsNeeded {
NSLog(@"Event File Doesn't Exists or New File Needed, Creating Connection");
NSURLRequest *feedURLRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:kEventFeedURL]];
self.eventsFeedConnection = [[NSURLConnectionWithTag alloc] initWithRequest:feedURLRequest delegate:self startImmediately:YES tag:0];
}
//Callback from DateStampParser
-(void)timeStampResponse:(NSNotification *)notif {
NSString *response = [[notif userInfo] objectForKey:@"TimeStampResponse"];
if ([response isEqualToString:@"NewEvents"]) {
[self newEventsNeeded];
self.appLoadingViewController.loadingLabel.text = @"New Events Found...";
} else if ([response isEqualToString:@"NoNewEvents"]){
[self allEventsLoaded];
}
}
以及 NSURLConnection 委托方法
-(void)connection:(NSURLConnectionWithTag *)connection didFailWithError:(NSError *)error {
if (connection.tag == 0) {
NSLog(@"Connection failed on Event Feed");
} else if (connection.tag == 1) {
NSLog(@"Connection failed on Time Stamp Check");
}
}
-(void)connection:(NSURLConnectionWithTag *)connection didReceiveResponse:(NSURLResponse *)response{
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
NSLog(@"connection:didRecieveResponse:NSHTTPURLResponse");
if ((([httpResponse statusCode]/100) == 2)) {
//Handling for eventsFeedConnection
if (connection.tag == 0) {
NSLog(@"Connection tag = 0");
self.eventsData = [NSMutableData data];
} else if (connection.tag == 1) {
NSLog(@"Connection tag = 1");
//NSLog(@"Timestamp connection received response");
self.timeStampData = [NSMutableData data];
}
} else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Network Error" message:@"No Response from the Server" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil];
[alert show];
[alert release];
}
}
-(void)connection:(NSURLConnectionWithTag *)connection didReceiveData:(NSData *)data{
//Handling for eventsFeedConnection
if (connection.tag == 0) {
self.appLoadingViewController.loadingLabel.text = @"Downloading Events...";
[eventsData appendData:data];
} else if (connection.tag == 1) {
self.appLoadingViewController.loadingLabel.text =@"Checking for New Events...";
[timeStampData appendData:data];
}
}
-(void)connectionDidFinishLoading:(NSURLConnectionWithTag *)connection{
//Handling for eventsFeedConnection
if (connection.tag == 0) {
NSLog(@"EventFeed Connection Finished");
self.eventsFeedConnection = nil;
[eventsFeedConnection release];
ParserOperation *parser = [[ParserOperation alloc] initWithData:self.eventsData];
[parseQueue addOperation:parser];
[parser release];
self.eventsData = nil;
//[eventCategoryListViewController reenableRefreshButton];
} else if (connection.tag ==1){
NSLog(@"TimeStamp Connection Finished");
self.timeStampConnection = nil;
[timeStampConnection release];
DateStampParser *parser = [[DateStampParser alloc] initWithData:self.timeStampData];
[parseQueue addOperation:parser];
[parser release];
self.timeStampData = nil;
}
}
不确定仅此而已是否显而易见代码或问题是什么,但如果需要任何额外的代码/需要澄清我想要完成的任务,请告诉我。
感谢
为了清晰起见进行编辑 只是为了澄清,来自 newEventsNeeded 的 NSLog 被触发,但只有委托方法不会被触发。
I've looked all over for answers to this question and have seen a lot of similar issues but the solutions did not seem to pertain to my situation. I'm very new to iOS development so any help would be appreciated.
The current app is looking to display events happening in a city based on an XML feed being generated by their website. I'm storing the events in a plist and checking for new events explicitly on app load. The current process is as follows:
- Application launches and makes a NSURLConnection to check the server for a timestamp and download it.
- Checks the newly downloaded timestamp vs the local timestamp to see if it is greater. If it is, it rewrites the file containing the plist and fires a notification that new events are needed.
This is where the second NSURLConnection does not seem to fire. The callback method itself fires but it does not seem like the delegate methods fire after.
The strange thing is that if I call both connections at the same time, as opposed to one as a result of the other, they both will fire and call the delegate methods.
Here is the code for some of the classes with some of the guts removed for clarity:
Application Delegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Set up analytics account
// Set the tab bar controller as the window's root view controller and display.
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
//Set up listeners for event handling
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(timeStampResponse:) name:@"TimeStampResponse" object:nil];
//Set app loading screen
//Create new OperationQueue, set ActivityIndicator and run TimeStamp Check
parseQueue = [NSOperationQueue new];
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
[self timeStampCheck];
return YES;
}
-(void)timeStampCheck {
NSLog(@"Time Stamp Check, Creating Connection");
NSURLRequest *timeStampURLRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:kTimeStampURL]];
self.timeStampConnection = [[NSURLConnectionWithTag alloc] initWithRequest:timeStampURLRequest delegate:self startImmediately:YES tag:1];
}
-(void)newEventsNeeded {
NSLog(@"Event File Doesn't Exists or New File Needed, Creating Connection");
NSURLRequest *feedURLRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:kEventFeedURL]];
self.eventsFeedConnection = [[NSURLConnectionWithTag alloc] initWithRequest:feedURLRequest delegate:self startImmediately:YES tag:0];
}
//Callback from DateStampParser
-(void)timeStampResponse:(NSNotification *)notif {
NSString *response = [[notif userInfo] objectForKey:@"TimeStampResponse"];
if ([response isEqualToString:@"NewEvents"]) {
[self newEventsNeeded];
self.appLoadingViewController.loadingLabel.text = @"New Events Found...";
} else if ([response isEqualToString:@"NoNewEvents"]){
[self allEventsLoaded];
}
}
And the NSURLConnection Delegate methods
-(void)connection:(NSURLConnectionWithTag *)connection didFailWithError:(NSError *)error {
if (connection.tag == 0) {
NSLog(@"Connection failed on Event Feed");
} else if (connection.tag == 1) {
NSLog(@"Connection failed on Time Stamp Check");
}
}
-(void)connection:(NSURLConnectionWithTag *)connection didReceiveResponse:(NSURLResponse *)response{
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
NSLog(@"connection:didRecieveResponse:NSHTTPURLResponse");
if ((([httpResponse statusCode]/100) == 2)) {
//Handling for eventsFeedConnection
if (connection.tag == 0) {
NSLog(@"Connection tag = 0");
self.eventsData = [NSMutableData data];
} else if (connection.tag == 1) {
NSLog(@"Connection tag = 1");
//NSLog(@"Timestamp connection received response");
self.timeStampData = [NSMutableData data];
}
} else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Network Error" message:@"No Response from the Server" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil];
[alert show];
[alert release];
}
}
-(void)connection:(NSURLConnectionWithTag *)connection didReceiveData:(NSData *)data{
//Handling for eventsFeedConnection
if (connection.tag == 0) {
self.appLoadingViewController.loadingLabel.text = @"Downloading Events...";
[eventsData appendData:data];
} else if (connection.tag == 1) {
self.appLoadingViewController.loadingLabel.text =@"Checking for New Events...";
[timeStampData appendData:data];
}
}
-(void)connectionDidFinishLoading:(NSURLConnectionWithTag *)connection{
//Handling for eventsFeedConnection
if (connection.tag == 0) {
NSLog(@"EventFeed Connection Finished");
self.eventsFeedConnection = nil;
[eventsFeedConnection release];
ParserOperation *parser = [[ParserOperation alloc] initWithData:self.eventsData];
[parseQueue addOperation:parser];
[parser release];
self.eventsData = nil;
//[eventCategoryListViewController reenableRefreshButton];
} else if (connection.tag ==1){
NSLog(@"TimeStamp Connection Finished");
self.timeStampConnection = nil;
[timeStampConnection release];
DateStampParser *parser = [[DateStampParser alloc] initWithData:self.timeStampData];
[parseQueue addOperation:parser];
[parser release];
self.timeStampData = nil;
}
}
Not sure if it may be obvious from just this code or not what the problem is but if any additional code is needed/clarification on what I'm trying to accomplish is needed please let me know.
Thanks
edit for clarity
Just to clarify, the NSLog from newEventsNeeded fires, but just the delegate methods don't get fired.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
确保启动 NSURLConnection 的线程有一个运行循环。
NSURLConnection
的异步回调被分派到调用线程的运行循环上。如果调用线程(在本例中,它似乎是一个 NSOperation 队列)没有运行循环,或者它没有在默认运行循环模式下运行,那么您将看不到任何委托回调。您第一次调用[self timeStampCheck]
是在主线程上,所以没关系。您后面的调用来自操作队列,该队列可能没有运行循环。文档中的相关片段:
Make sure the thread starting the
NSURLConnection
s has a runloop.NSURLConnection
's asynchronous callbacks are dispatched onto the calling threads runloop. If the calling thread (in this case, it seems to be anNSOperation
queue) doesn't have a runloop, or if it's not operating in the default run loop mode, you won't see any delegate callbacks. Your first call to[self timeStampCheck]
is on the main thread, so that's fine. Your later calls are from the operation queue, which possibly has no runloop.The relevant snippet from the documentation: