Обновите NSTextField с X из Y при загрузке файлов - PullRequest
1 голос
/ 03 ноября 2011

Я пытаюсь обновить «метку состояния», NSTextField, с текущими значениями (X) всего (Y) при загрузке файлов из NSURLConnection.Ниже приведен код, который работает, но не на 100%, или как мне хотелось бы.

X = runningCurrent
Y = runningTotal

Следующий код обновляет (Y) или ofTotal правильно, однако, (X) или ток скачет повсюду и не увеличивается на 1, 2, 3 .. и т. д.

ApplicationController

- (void) updateLabelWithCurrent:(int)current ofTotal:(int)total
{
    [txtStatus setStringValue:[NSString stringWithFormat:@"Downloading %i of %i",current,total]];
    [txtStatus setNeedsDisplay:YES];
}

Источник данных XML

for (int x = 0; x < [catArray count]; x++) 
{  
    /*  download each file to the corresponding category sub-directory  */
    [[WCSWallpaperDownloader alloc] 
     initWithWallpaperURL: [NSURL URLWithString:[[catArray objectAtIndex:x] objectForKey:@"imageUrl"]] 
     andFileOutput: [NSString stringWithFormat:@"%@/%@_0%i.jpg",cat,catName,x] withCurrent:x ofTotal:[catArray count]]; 
}

WCSWallpaperDownloader

- (id)initWithWallpaperURL:(NSURL *)imageUrl andFileOutput:(NSString*)fileOutput withCurrent:(int)current ofTotal:(int)total
{
    self = [super init];
    if (self) 
    {        
        appController = [[ApplicationController alloc] init];

        self.fileOut = fileOutput;

        NSURLRequest *imageRequest = 
        [NSURLRequest requestWithURL:imageUrl cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:1800.0];
        [[NSURLConnection alloc] initWithRequest:imageRequest delegate:self];

        runningCurrent = current;
        runningTotal   = total;
    }
    return self;
}

#pragma mark NSURLConenction

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response 
{
    receivedData = [[NSMutableData data] retain]; 
    [receivedData setLength:0];  
} 
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data  {
    [receivedData appendData:data];
}  
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    /*  release the connection, and the data object  */
    [connection release];
    [receivedData release];

    NSLog(@"Connection failed! Error - %@ %@",
          [error localizedDescription],
          [[error userInfo] objectForKey:NSErrorFailingURLStringKey]);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection  
{

    /*  updates the status label with the current download of total objects being downloaded  */
    [appController updateLabelWithCurrent: runningCurrent ofTotal: runningTotal];

    /*  skip existing files  */
    if ( ! [MANAGER fileExistsAtPath:fileOut] )
    {
        [receivedData writeToFile:fileOut atomically:YES];
        [receivedData release];
    }
    [[appController txtStatus] setStringValue:@""];
}

Решение

Следующий код корректно увеличивает состояние загрузки после завершения каждого объекта.

- (void) incrementStatusLabelWithTotal:(int)total
{
    runningCurrent++;
    [txtStatus setStringValue:[NSString stringWithFormat:@"Downloading %i of %i",runningCurrent,total]];
}

1 Ответ

1 голос
/ 03 ноября 2011

Похоже, что вы запускаете загрузки по одному, но они не заканчиваются в одном и том же порядке - поэтому вы создаете каждый объект, сообщая ему, что он загружает элемент X из Y, но если объект 6, загружающий объект, завершаетдо того, как объект загрузит элемент 4, ваш X будет, как вы говорите, повсюду.

Каждый загрузчик обоев должен просто сообщить appController, что он завершен, и позволить appController содержать количество загруженных на данный момент элементов и общее количество.

На самом деле, загрузчикам обоев на самом деле не нужно знать, сколько загрузок происходит, или какой именно они номер.Ваш источник данных XML должен сообщать вашему «контроллеру приложения» об общем количестве загрузок, а затем каждый загрузчик, когда он завершает, должен сообщать контроллеру, что это сделано.

Итак, ваш текущий метод инициализации будет просто:

- (id)initWithWallpaperURL:(NSURL *)imageUrl andFileOutput:(NSString*)fileOutput

Я не уверен, что вам следует каждый раз в этом методе выделять новый экземпляр appController - остальной кодПохоже, должен быть один из них, который отображает одну метку, фактически делегат для загрузчика?Возможно, это должно быть назначено источником данных XML при создании каждого объекта?

После завершения загрузки ваш метод connectionDidFinishLoading будет выглядеть примерно так:

[appController downloaderDidFinishDownloading:self];

Что вызоветметод в вашем appController, который выглядит примерно так:

-(void)downloaderDidFinishDownloading:(WCSWallpaperDownloader*)downloader
{
    completedDownloads++;
    [txtStatus setStringValue:[NSString stringWithFormat:@"Downloaded %i of %i",completedDownloads,totalDownloads]];
}

Где completedDownloads и totalDownloads - это ивары в вашем классе контроллера приложения.

...