在自定义委托块UI中执行工作 - 为什么?

时间:2011-05-26 17:46:16

标签: objective-c cocoa-touch ios delegates

我写了一个自定义的“JSON fetcher”。在我的视图控制器中,我调用了[loader start];,当loader完成时,它会运行委托方法[self.delegate doneLoading];

这一切都有效,但UI被阻止 - 无法移动任何东西 - 直到加载完成。我认为如果我通过自己的委托方法加载,这不会发生。我在这里错过了什么?我需要调用一些额外的方法吗?

- (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,但这可以运行smoothley ...

2 个答案:

答案 0 :(得分:2)

这是在主线程上运行,阻塞其他所有内容。您必须在后台进行加载。使用performSelectorInBackground:withObject在后​​台进行加载,如果委托方法应该影响UI,则应该将请求发送回主线程。

答案 1 :(得分:1)

您的方法很好,但您需要编写代码以将[loader start]中正在完成的工作放入后台线程中。现在,控制流继续进入[loader start]并执行您在那里编写的任何代码,调用您的委托,并在调用start后返回到下一行代码。

在不知道你正在做什么的情况下,我无法确切地说如何完成背景线程,但是看看NSOperationQueue和NSURLConnection异步方法将是一个很好的起点。