我有一个tableView,它按如下方式加载XML Feed:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
if ([stories count] == 0) {
NSString *path = @"http://myurl.com/file.xml";
[self parseXMLFileAtURL:path];
}
}
我想让微调器在应用程序启动时显示在顶栏上,并在数据显示在我的tableView上后显示消息。
我认为将开头放在viewDidAppear并将结尾放在-(void)parserDidEndDocument:(NSXMLParser *)parser
但是它不起作用。
我很欣赏有关如何实施此解决方案的解决方案。
答案 0 :(得分:5)
问题在于:NSXMLParser
是一个同步API。这意味着只要在parse
上调用NSXMLParser
,该线程就会完全解析xml,这意味着没有UI更新。
以下是我通常如何解决这个问题:
- (void) startThingsUp {
//put the spinner onto the screen
//start the spinner animating
NSString *path = @"http://myurl.com/file.xml";
[self performSelectorInBackground:@selector(parseXMLFileAtURL:) withObject:path];
}
- (void) parseXMLFileAtURL:(NSString *)path {
//do stuff
[xmlParser parse];
[self performSelectorOnMainThread:@selector(doneParsing) withObject:nil waitUntilDone:NO];
}
- (void) doneParsing {
//stop the spinner
//remove it from the screen
}
我多次使用过这种方法,效果很好。
答案 1 :(得分:3)
如果你想做一些应该在主线程上开始的事情,开始一个新线程可能会过度使用并且是一个复杂的来源。
在我自己的代码中,我需要通过按下按钮来启动MailComposer,但它可能需要一些时间才能出现,我想确保UIActivityIndicator同时旋转。
这就是我的所作所为:
- (无效)submit_Clicked:(ID)事件 { [self.spinner startAnimating]; [self performSelector:@selector(displayComposerSheet)withObject:nil afterDelay:0]; }
它将对displayComposerSheet进行排队,而不是立即执行它。足够让微调器开始制作动画!
答案 2 :(得分:2)
我通常会实现一个NSTimer,它将调用我的spinner方法,我在进行繁重的工作之前就开始了(通常会阻塞主线程的工作)。
NSTimer触发并调用我的微调器方法。主要工作完成后,我禁用微调器。
代码就像:
IBOutlet UIActiviyIndicatorView *loginIndicator;
{
...
[loginIndicator startAnimating];
[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(executeAuthenticationRequest)
userInfo:nil repeats:NO];
...
}
- (void) executeAuthenticationRequest
{
/* Simulate doing a network call. */
sleep(3);
[loginIndicator stopAnimating];
...
}
你也可以这样做:
IBOutlet NSProgressIndicator *pIndicator;
开始:
[pIndicator startAnimation:self];
[pIndicator setHidden:NO];
停止:
[pIndicator stopAnimation:self];
[pIndicator setHidden:YES];
答案 3 :(得分:1)
在Cocoa(和大多数其他应用程序框架)中,用户界面由主线程更新。操作视图时,通常不会重新绘制视图,直到控件返回到运行循环并更新屏幕。
因为您正在解析主线程中的XML,所以您不允许更新屏幕,这就是您的活动指示器没有出现的原因。
您应该可以通过执行以下操作来解决此问题:
在viewDidAppear中,显示/动画微调器,然后调用
[self performSelector:@selector(myXMLParsingMethod)withObject:nil afterDelay:0];
在myXMLParsingMethod中,解析XML,然后隐藏/停止微调器。
这样,控件将在解析开始之前返回到运行循环,以允许微调器开始动画。