方法被调用两次

时间:2012-01-04 21:07:59

标签: objective-c methods nsurlconnection

我正在进行NSURLConnection,只有在有新文件时才会下载文件(使用上次修改日期进行检查)。但要实现这一点,我使用两种不同的NSURLRequests和NSURLConnection方法。嗯,他们做同样的事情。

    - (IBAction)uppdatera:(id)sender
{
    checkHeaders = YES;

    NSURLRequest *theRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.forellgatan.se/site/ftp_files/Kapareskolan.zip"] cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:10.0];

    NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];

    if (theConnection) 
    {
        self.receivedData = [[NSMutableData data] retain];
    } 

    else
    {
        UIAlertView *connectFailMessage = [[UIAlertView alloc] initWithTitle:@"Ingen internetanslutning! 1" message:@"Anslut dig till internet för att ladda ner!"  delegate: self cancelButtonTitle:@"Ok" otherButtonTitles: nil];
        [connectFailMessage show];
        [connectFailMessage release];        
    }
}

- (void)downloadNewFile
{
    NSURLRequest *theRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.forellgatan.se/site/ftp_files/Kapareskolan.zip"] cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:10.0];

    NSURLConnection *theConnection2 = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];

    if (theConnection2) 
    {
        self.receivedData = [[NSMutableData data] retain];
    } 

    else
    {
        UIAlertView *connectFailMessage = [[UIAlertView alloc] initWithTitle:@"Ingen internetanslutning! 2" message:@"Anslut dig till internet för att ladda ner!"  delegate: self cancelButtonTitle:@"Ok" otherButtonTitles: nil];
        [connectFailMessage show];
        [connectFailMessage release];        
    }

    checkHeaders = NO;

    self.progressView.hidden = NO;
}

它通过didReceiveResponse方法:

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    if (checkHeaders == YES)
    {
        NSHTTPURLResponse *test = (NSHTTPURLResponse *)response;

        if ([test respondsToSelector:@selector(allHeaderFields)])
        {
            NSDictionary *metaData = [test allHeaderFields];

            NSString *lastModifiedString = [metaData objectForKey:@"Last-Modified"];

            NSString *savedString = [[NSUserDefaults standardUserDefaults] stringForKey:@"LastModified"];

            if (![lastModifiedString isEqualToString:savedString])
            {
                [self downloadNewFile];
            }

            else if ([lastModifiedString isEqualToString:savedString])
            {       
                UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Ingen uppdatering tillgänglig" message:@"Det finns ingen uppdatering att hämta just nu." delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil];
                [alert show];
                [alert release];
            }

            NSUserDefaults *standardUserDefaults = [NSUserDefaults standardUserDefaults];
            [standardUserDefaults setObject:lastModifiedString forKey:@"LastModified"];
            [standardUserDefaults synchronize];
        }
    }

    [self.receivedData setLength:0];
    self.fileSize = [[NSNumber numberWithLong: [response expectedContentLength]] retain];
}

最后的connectionDidFinishLaunching方法:

    - (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    if (checkHeaders == NO)
    {
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
        NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
        [self.receivedData writeToFile:[basePath stringByAppendingPathComponent:@"Kapareskolan.zip"] atomically:YES];

        [self unzipDownloadedFile];

        self.progressView.hidden = YES;

        NSLog(@"Finished...");
    }

    [connection cancel];
}

我知道didFinishLaunching方法会被调用两次,但是我想知道如何进行,所以如果有更新,方法不会被调用两次?

我知道这里有很多问题和很多代码,但只是给我一个提示,我会非常感激。

2 个答案:

答案 0 :(得分:2)

如果您已经完成了didReceiveResponse方法中的第一个连接对象,那么您应该取消它。否则它将进入connectionDidFinishLoading方法。 我想这就是你想要的:

if (![lastModifiedString isEqualToString:savedString])
  {
    [connection cancel];
    [self downloadNewFile];
  }

此外,看起来您在启动第二个请求后将checkHeaders设置为NO,这可能会导致竞争条件。

答案 1 :(得分:1)

根据programming guide,在委托收到connectionDidFinishLoading:或connection:didFailWithError:message之前,可以通过向连接发送取消消息来随时取消连接“。

所以为什么不尝试移动

      [connection cancel];

connectionDidFinishLoading方法到if-else委托方法中的didReceiveResponse块之后?您希望在任何一种情况下取​​消“checkHeaders == YES”连接;或者您要开始新的连接,或者您已经知道当前连接需要知道的所有内容。

按要求更新:

  if (![lastModifiedString isEqualToString:savedString]) {
      [self downloadNewFile];
  } else { // you've already implicitly checked for equality above
      UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Ingen uppdatering tillgänglig" message:@"Det finns ingen uppdatering att hämta just nu." delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil];
      [alert show];
      [alert release];
  }
  // you've used the connection for everything that you need, so cancel it in either case
  [connection cancel];

downloadNewFile异步启动NSURLConnection时,如果两个字符串相等,这应该没问题。稍微更安全的是将cancel方法调用移到if-else检查之前。