我的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];
}
答案 0 :(得分:8)
我想说你的问题是你在后台线程上操作UI。 documentation清楚地表明你不应该这样做:
您正在使用的注意:在大多数情况下,UIKit类只能从应用程序的主线程中使用。对于从
UIResponder
派生的类或者以任何方式操纵应用程序的用户界面的类尤其如此。
UIActivityIndicatorView
继承自UIResponder
,因此您所做的事情属于“特别真实”的情况。
您可能正在对主线程进行长时间的同步工作,这是将工作分成多个线程的开头。为此,我有两件事要说:
听起来您在主线程上保留了工作/数据处理/网络/其他长时间运行的同步任务,并选择将UI更新分派给另一个线程。正如文档(上面引用的)所说,这是错误的顺序。您应该在后台执行任何长时间运行的同步任务,并在UI需要更新时回调主线程。
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。