我写了一个自定义的“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 ...
答案 0 :(得分:2)
这是在主线程上运行,阻塞其他所有内容。您必须在后台进行加载。使用performSelectorInBackground:withObject
在后台进行加载,如果委托方法应该影响UI,则应该将请求发送回主线程。
答案 1 :(得分:1)
您的方法很好,但您需要编写代码以将[loader start]
中正在完成的工作放入后台线程中。现在,控制流继续进入[loader start]
并执行您在那里编写的任何代码,调用您的委托,并在调用start后返回到下一行代码。
在不知道你正在做什么的情况下,我无法确切地说如何完成背景线程,但是看看NSOperationQueue和NSURLConnection异步方法将是一个很好的起点。