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

发布于 2024-11-10 02:34:22 字数 2063 浏览 0 评论 0原文

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

这一切都有效,但是 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 但这工作顺利......

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

乖乖公主 2024-11-17 02:34:22

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

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.

诗笺 2024-11-17 02:34:22

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

如果不了解更多关于您正在做什么的信息,我无法确切地说出如何完成后台线程,但是看一下 NSOperationQueue 和 NSURLConnection 异步方法将是一个很好的起点。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文