Метод вызывается два раза - PullRequest
0 голосов
/ 05 января 2012

Я делаю 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 ]

2 голосов
/ 05 января 2012

Если вы завершили работу с первым объектом подключения в методе didReceiveResponse, вам следует отменить его.В противном случае это будет сделано для метода connectionDidFinishLoading.Я думаю, это то, что вы хотите:

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

Также похоже, что вы устанавливаете checkHeaders в NO после запуска второго запроса, что может вызвать состояние гонки.

1 голос
/ 05 января 2012

Согласно руководству по программированию , соединение "можно отменить в любое время до того, как делегат получит connectionDidFinishLoading: или connection: didFailWithError: сообщение, отправив соединению сообщение об отмене".* так почему бы не попробовать переместить

      [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.

...