后续 NSURLConnections 不触发委托方法

发布于 2024-11-29 01:25:50 字数 4907 浏览 0 评论 0原文

我已经到处寻找这个问题的答案,并且看到了很多类似的问题,但解决方案似乎并不适合我的情况。我对 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

漆黑的白昼 2024-12-06 01:25:50

确保启动 NSURLConnection 的线程有一个运行循环。 NSURLConnection 的异步回调被分派到调用线程的运行循环上。如果调用线程(在本例中,它似乎是一个 NSOperation 队列)没有运行循环,或者它没有在默认运行循环模式下运行,那么您将看不到任何委托回调。您第一次调用 [self timeStampCheck] 是在主线程上,所以没关系。您后面的调用来自操作队列,该队列可能没有运行循环。

文档中的相关片段

委托

连接的委托对象。代表将收到
随着加载的进行委托消息。给代表的消息
将在调用此方法的线程上发送。用于连接
为了正确工作,调用线程的运行循环必须运行在
默认运行循环模式。

Make sure the thread starting the NSURLConnections 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 an NSOperation 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:

delegate

The delegate object for the connection. The delegate will receive
delegate messages as the load progresses. Messages to the delegate
will be sent on the thread that calls this method. For the connection
to work correctly, the calling thread’s run loop must be operating in
the default run loop mode.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文