一段时间后制作动画的背景线程上的运行方法停止

时间:2014-05-23 11:10:47

标签: ios objective-c multithreading uiactivityindicatorview

我的app委托有两种方法来启动和停止活动指示器。我需要在后台线程上调用它们,以便它始终可见。像这样:

[self.delegate performSelectorInBackground:@selector(acionarActivityIndicator) withObject:nil];

[NSThread detachNewThreadSelector:@selector(acionarActivityIndicator) toTarget:self.delegate withObject:nil];

两者都是一样的。

假设这是VCA按钮点击,然后,在VCB加载所有内容之后,我在我的应用委托中调用另一个方法来停止动画。我在后台对两个视图执行其他操作以获取我的数据。

活动指标工作正常。问题是,过了一段时间,我的应用程序中的所有动画都停止工作。我觉得这与此有关,但我不确定。

如果我尝试更快地进行屏幕转换,我会更早地收到此错误。那有意义吗?

App Delegate方法:

- (void)acionarActivityIndicator {
    // Show the activity indicator
    self.view = [[UIView alloc] init];
    self.activityIndicator = [[UIActivityIndicatorView alloc] init];

    self.view.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5];
    self.view.frame = self.window.bounds;
    self.activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
    CGRect frame = self.view.frame;
    self.activityIndicator.center = CGPointMake(frame.size.width/2, frame.size.height/2);
    [self.view addSubview:self.activityIndicator];
    [self.activityIndicator startAnimating];
    [self.window addSubview:self.view];
    [self.window makeKeyAndVisible];
}

- (void)pararActivityIndicator
{
    // metodo parar activity indicator
    [self.view removeFromSuperview];
    [self.activityIndicator stopAnimating];
}

1 个答案:

答案 0 :(得分:8)

我想说你的问题是你在后台线程上操作UI。 documentation清楚地表明你不应该这样做:

  

注意:在大多数情况下,UIKit类只能从应用程序的主线程中使用。对于从UIResponder派生的类或者以任何方式操纵应用程序的用户界面的类尤其如此。

您正在使用的

UIActivityIndicatorView继承自UIResponder,因此您所做的事情属于“特别真实”的情况。


您可能正在对主线程进行长时间的同步工作,这是将工作分成多个线程的开头。为此,我有两件事要说:

1。你以错误的方式划分工作

听起来您在主线程上保留了工作/数据处理/网络/其他长时间运行的同步任务,并选择将UI更新分派给另一个线程。正如文档(上面引用的)所说,这是错误的顺序。您应该在后台执行任何长时间运行的同步任务,并在UI需要更新时回调主线程。

2。有些技术比NSThread

更容易使用

您选择使用NSThread或其他线程相关技术来划分您的工作。虽然在其他平台上就是这种情况。 iOS更喜欢使用队列进行并发。

在较低级别,您可以使用Grand central dispatch(简称GCD),它允许您在主队列或后台队列上排队。您还有NSOperations将工作划分为可以在彼此之间具有依赖关系的操作。


对于你正在做的事情,我会尝试这些方法:

- (IBAction)doHeavyWork:(id)sender
{
    /* start the activity indicator (you are now on the main queue) */

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        /* Do some heavy work (you are now on a background queue) */

        dispatch_sync(dispatch_get_main_queue(), ^{
            /* stop the activity indicator (you are now on the main queue again) */
        });
    });
}

另外,再看看UIKit文档,也许是iOS App Programming Guide