在自定义委托块 UI 中执行工作 - 为什么?
我写了一个自定义的“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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是在主线程上运行的,它阻塞了其他一切。您必须在后台进行加载。使用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.您的方法很好,但是您需要编写代码以将
[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.