Выполнение работы в пользовательском интерфейсе делегатских блоков - почему? - PullRequest
1 голос
/ 26 мая 2011

Я написал пользовательский "JSON fetcher". Из моего контроллера представления я вызываю [loader start];, и когда loader завершается, он запускает метод делегата [self.delegate doneLoading];.

Это все работает, однако пользовательский интерфейс заблокирован - не может ничего перемещать - пока не будет загружен загрузчик. Я думал, что если бы я выполнял загрузку через свой собственный метод делегата, этого бы не случилось. Что мне здесь не хватает? Есть ли какой-то дополнительный метод, который мне нужно вызвать?

- (void)getBandArray
{
    if (![self localBandVersion] || [self remoteBandVersion] > [self localBandVersion] || !CACHING) {
        NSLog(@"Band array loaded remotely.");
    [self startLoadingBands];
}else{
    NSLog(@"Band array loaded from disk.");
    [self loadBandsFromDisk];

    }
}

startLoadingBands запускает NSURLConnection, loadBandsFromDisk выглядит следующим образом:

- (void)loadBandsFromDisk
{
    NSData *dataFromDisk = [NSData dataWithContentsOfFile:[self fileStringForTag:JNKBandTag]];
if (dataFromDisk) {
    NSLog(@"Found band cache on disk...");

    NSString *strToParse = [[NSString alloc] initWithData:dataFromDisk encoding:NSUTF8StringEncoding];
    SBJsonParser *jsonObject = [[SBJsonParser alloc] init];
    NSError *jsonError;
    NSArray *parsedResult = [jsonObject objectWithString:strToParse error:&jsonError];
    [strToParse release];
    [jsonObject release];

    if (parsedResult && [parsedResult count] > 0) {
        NSLog(@"Parsed bands, handing over to delegate...");

        NSMutableArray *bandArray = [NSMutableArray array];
        for (NSDictionary *bandDict in parsedResult) {
            [bandArray addObject:[JNKBand bandWithDictionary:bandDict]];
        } 

        if ([self.delegate respondsToSelector:@selector(bandArrayArrived:)]) {
            [self.delegate bandArrayArrived:bandArray];
        }
    }else{
        NSLog(@"Error parsing bands, calling delegate...");
        if ([self.delegate respondsToSelector:@selector(bandArrayFailed)]) {
            [self.delegate bandArrayFailed];
        }
    }        
}else{
    if ([self.delegate respondsToSelector:@selector(bandArrayFailed)]) {
        [self.delegate bandArrayFailed];
    }
}
}

Странно то, что, как только соединение завершено, оно также в конечном итоге вызывает loadFileFromDisk, но это работает гладко ...

Ответы [ 2 ]

2 голосов
/ 26 мая 2011

Это работает в главном потоке, который блокирует все остальное.Вам придется делать загрузку в фоновом режиме.Используйте performSelectorInBackground:withObject для загрузки в фоновом режиме, и если метод делегата должен влиять на пользовательский интерфейс, вы должны отправить запрос обратно в основной поток.

1 голос
/ 26 мая 2011

Ваш подход хорош, но вам нужно написать код для помещения работы, выполняемой в [loader start], в фоновый поток. Прямо сейчас поток управления просто переходит в [loader start] и выполняет любой код, который вы там написали, вызывает ваш делегат и возвращается к следующей строке кода после вызова start.

Не зная больше о том, что вы делаете, я не могу точно сказать, как выполнить фоновую многопоточность, но было бы неплохо начать с NSOperationQueue и асинхронных методов NSURLConnection.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...