iPhone活动指示灯被延迟?
因此,当我点击我的mapView中的标注附件时,几秒钟内没有任何反应,因为它正在发出url请求并解析它,所以我想显示活动指示器,以便用户不认为它已冻结。下面的代码:iPhone活动指示灯被延迟?
- (void)mapView:(MKMapView *)mv annotationView:(MKAnnotationView *)pin calloutAccessoryControlTapped:(UIControl *)control {
// start activity indicator
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
NSLog(@"tapped");
ArtPiece *artPiece = (ArtPiece *)pin.annotation;
//when annotation is tapped switches page to the art description page
artDescription *artD = [[artDescription alloc] initWithNibName:@"artDescription" bundle:nil];
artD.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
artD.startingLocation = mapView.userLocation.location.coordinate;
artD.selectedArtPiece = artPiece;
NSLog(@"0");
[self presentModalViewController:artD animated:YES];
NSLog(@"1");
[artD loadArt:artPiece];
NSLog(@"2");
// stop activity indicator
//[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
[artD release];
}
奇怪(我反正,也许我失去了一些东西明显,因为我很没有经验),活动指示灯不显示,直到方法完成后,和模态视图开始动画到视图中。我把NSLogs放进去看看需要花费什么时间。我在“0”和“1”之间停顿了2秒,在“1”和“2”之间停了两秒钟。然后指标终于显示出来,所以我确信它由于某种原因一直等到该方法结束。任何想法为什么?
的变化到UI,显示活动的指标,不生效直到控制权返回到应用程序的main run loop。直到方法结束并且堆栈解除后才会发生这种情况。你需要展示活动的指标,然后甩了你正在等待到后台线程活动:
[self performSelectorInBackground:@selector(doThingINeedToWaitFor:)
withObject:anObject];
(注意苹果recommends你move away from using threads explicitly; performSelectorInBackground:withObject:
是让流失的最简单的方法,一些代码的主要更复杂的选项可用于其他情况请参阅Concurrency Programming Guide)
重要的问题是UI更新仍然需要在主线程上处理,因此在该方法中,工作完成后,您需要回电停止活动指示灯:
- (void) doThingINeedToWaitFor: (id)anObject {
// Creating an autorelease pool should be the first thing
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// Do your work...
// ...
// Update the UI back on the main thread
[self performSelectorOnMainThread:@selector(allDoneWaiting:)
withObject:nil
waitUntilDone:YES];
// Clear out the pool as the final action on the thread
[pool drain];
}
在您的回调方法中,您会再次隐藏活动指示符并执行必要的任何其他后处理。
您不能在同一功能中启动和停止活动指示器。
见我提供了这个问题的答案:How show activity-indicator when press button for upload next view or webview?
编辑为清楚:
- (void) someFunction
{
[activityIndicator startAnimation];
// do computations ....
[activityIndicator stopAnimation];
}
上面的代码将无法工作,因为你不给UI时间更新时,您包括activityIndicator在你当前运行的函数中。所以我和其他许多人做的是把它分解成一个单独的线程像这样:
- (void) yourMainFunction {
activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
[NSThread detachNewThreadSelector:@selector(threadStartAnimating) toTarget:self withObject:nil];
//Your computations
[activityIndicator stopAnimating];
}
- (void) threadStartAnimating {
[activityIndicator startAnimating];
}
UI变化需要在主线程中发生。活动指示器需要在'yourMainFunction'中开始动画,一个线程需要被“分离”(GCD,NSOperation,NSThread,POSIX)来执行计算,然后回调主线程以停止动画。 – Joe
东西正在放缓您的微调。我会建议在后台使用一个线程来完成你的繁重工作。试试这个:
-(void)myMethod{
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
[NSThread detachNewThreadSelector:@selector(startWorkingThread) toTarget:self withObject:nil];
}
-(void)startWorkingThread{
//Heavy lifting
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}
我假设你有评论的:
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
出于测试目的...
所以allDoneWaiting会成为另一种方法:[UIApplication sharedApplication] .networkActivityIndicatorVisible = YES; ? – Ryan
它可能会根据您的需要做其他事情,但基本上,是的。任何接触GUI的代码都需要在主线程上运行。 –
好的谢谢你的帮助,还有一个问题:它崩溃并抱怨一个autorelease池,我需要围绕doThingINeedToWaitFor方法做些什么吗? – Ryan