Iphone 带有UIActivityIndicator视图的活动指示器(微调器)

Iphone 带有UIActivityIndicator视图的活动指示器(微调器),iphone,objective-c,cocoa-touch,Iphone,Objective C,Cocoa Touch,我有一个加载XML提要的tableView,如下所示: - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; if ([stories count] == 0) { NSString *path = @"http://myurl.com/file.xml"; [self parseXMLFileAtURL:path]; } } 我想让微调器在应用程序

我有一个加载XML提要的tableView,如下所示:

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];

    if ([stories count] == 0) {
        NSString *path = @"http://myurl.com/file.xml";
        [self parseXMLFileAtURL:path];
    }
}
我想让微调器在应用程序启动时显示在顶部栏上,并在数据显示在我的tableView上后消失

我认为将开头放在view上,将结尾放在
-(void)parserdinddocument:(NSXMLParser*)parser上,但它不起作用


对于如何实现此解决方案,我非常感谢提供一个很好的解释性解决方案。

我通常会实现一个NSTimer,它将调用我的微调器方法,我会在开始执行繁重的工作(通常会阻塞主线程的工作)之前立即启动该方法

NSTimer启动,并调用my spinner方法。当主要工作完成时,我禁用微调器

代码如下:

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];
在Cocoa(和大多数其他应用程序框架)中,用户界面由主线程更新。操纵视图时,通常不会重新绘制视图,直到控件返回到运行循环并更新屏幕

因为您在主线程中解析XML,所以不允许屏幕更新,这就是为什么您的活动指示器没有出现的原因

您应该能够通过执行以下操作来修复它:

  • 在ViewDidDisplay中,显示/设置微调器动画,然后调用

    [自执行选择器:@selector(myXMLParsingMethod),对象:nil afterDelay:0]

  • 在myXMLParsingMethod中,解析XML,然后隐藏/停止微调器


  • 这样,控件将在解析开始之前返回到运行循环,以允许微调器开始设置动画。

    问题在于:
    NSXMLParser
    是一个同步API。这意味着,只要在
    NSXMLParser
    上调用
    parse
    ,该线程将完全无法解析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
    }
    

    我已经多次使用这种方法,而且效果很好。

    如果你想做一些应该从主线程开始的事情,那么启动一个新线程可能会造成过度的杀伤力和复杂性

    在我自己的代码中,我需要通过按下按钮启动MailComposer,但它可能需要一些时间才能出现,我希望确保UIActivityIndicator同时旋转

    我就是这么做的:

    -(无效)已单击提交:(id)事件 { [自旋转启动]; [自执行选择器:@选择器(DisplayComposer Sheet),对象:nil afterDelay:0]; }


    它将对工作表进行排队,而不是直接执行它。足以让微调器开始设置动画

    如果您计划了一个计时器,然后阻塞了主线程,那么计时器将不会被触发。或者你是说你把阻塞工作放在timerdfire:method中了?sleep(3)调用就是我假装在做的工作。谢谢!这正是我需要的。