开发者

Performing work in custom delegate blocks UI -- why?

I wrote a custom "JSON fetcher". From my view controller I call [loader start]; and when loader is done, it runs the delegate method [self.delegate doneLoading];.

This all works, however the UI is blocked -- can't move anything -- until the loader is done. I thought that if I did the loading over my own delegate method, this wouldn't happen. What am I missing here? Is there some extra method I need to call?

- (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 starts the NSURLConnection, loadBandsFromDisk looks like this:

- (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 开发者_如何学C= [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];
    }
}
}

The weird thing is that once the connection is finished it also eventually calls loadFileFromDisk but this works smoothley...


This is running on the main thread which is blocking everything else. You will have to do the loading in the background. Use performSelectorInBackground:withObject to do the loading in the background and if the delegate method is supposed to affect the UI, you should send the request back to the main thread.


Your approach is good, but you need to write code to put the work being done in [loader start] into a background thread. Right now the control flow just continues into [loader start] and executes whatever code you wrote there, calls your delegate, and returns to the next line of code after calling start.

Without knowing more about what you're doing I can't say exactly how to accomplish background threading, but taking a look at NSOperationQueue and the NSURLConnection asynchronous methods would be a good place to start.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜