该应用程序在iOS 7中正常运行,但当我疯狂切换到iOS 8时,该应用程序并没有像它想象的那样工作。在调试模式下,应用程序中的NSThread detachNewThreadSelector函数被调用以在前台创建一个忙盒以防止用户访问。主线程继续并调用Web服务来检索数据。一旦收到数据,就会调用另一个detachNewThreadSelector来关闭第一个线程。
在iOS 8中,当我在调试模式中单步执行时,在到达detachNewThreadSelector后,没有任何反应。第一个线程中的代码不会被执行。主线程继续打开并调用Web服务来检索数据。一旦接收到数据,就会到达第二个detachNewThreadSelector,但代码也不会被执行,直到它到达viewdidload函数的末尾。
dismissActivityIndicator的代码在CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION中执行,该代码将生成“从视图控制器中解除”的尝试'错误。然后它进入__CFRunLoopDoSources0,然后在__CFRunLoopRun中执行showActivityIndicator的代码。这会导致应用程序创建一个忙碌的框,因为dismissActivityIndicator已经被执行,所以无法将其关闭。不确定为什么在反向和viewdidload函数结束时调用这些函数。
这个项目传递给了我,所以我不熟悉如何生成弹出视图来阻止主线程,直到从源获取数据。我需要快速修复或解释修复iOS 8问题所发生的事情。
-(void)callService{
[NSThread detachNewThreadSelector: @selector(showActivityIndicator) toTarget:self withObject:NULL];
sleep(1);
//call web service
[NSThread detachNewThreadSelector: @selector(dismissActivityIndicator) toTarget:self withObject:NULL];
}
-(void)showActivityIndicator{
UISplitViewController *splitVC = [[self navigationController] splitViewController];
UINavigationController *detailVC = [[splitVC viewControllers] objectAtIndex:1];
activityIndicatorVC = [[ActivityIndicatorVC alloc] init];
[activityIndicatorVC setModalTransitionStyle:UIModalTransitionStyleCoverVertical];
[activityIndicatorVC setModalPresentationStyle:UIModalPresentationFormSheet];
[detailVC presentViewController:activityIndicatorVC animated:NO completion: nil];
CGRect r2 = CGRectMake(detailVC.view.bounds.size.width/2 - 80,
detailVC.view.bounds.size.height/2 - 150, 160, 160);
r2 = [detailVC.view convertRect:r2 toView:activityIndicatorVC.view.superview.superview];
activityIndicatorVC.view.superview.frame = r2;
}
-(void)dismissActivityIndicator{
UISplitViewController *splitVC = [[self navigationController] splitViewController];
UINavigationController *detailVC = [[splitVC viewControllers] objectAtIndex:1];
[detailVC dismissModalViewControllerAnimated:NO];
}
答案 0 :(得分:2)
主线程继续并调用Web服务来检索数据
我不熟悉如何生成弹出视图来阻止主线程,直到从源获取数据。
不要在主线程上做这些事情!如果你只为UI使用主线程,那么像这样的问题就解决了。当然,对于任何不得不等待其他东西的事情都不会。
你也在(大概)主线程上做了sleep(1);
,由于类似的原因这很糟糕。此外,您几乎不需要使用sleep
进行适当的设计。使用sleep
是一个很好的指标,你不懂线程。
现在回答(可能)
我很难理解为什么要将showActivityIndicator
和dismissActivityIndicator
分离到自己的主题。除了主线程之外的任何操作的UI操作通常不仅是未定义的行为(不是线程安全的),而且通常是一个坏主意。
其次,您将它们分离到不同的线程,以便它们同时运行 。显然这是不你想要的。需要在webservice调用返回后运行dismissActivityIndicator
,而不是之前。您已从代码中删除了showActivityIndicator
和dismissActivityIndicator
之间的实际调用,因此谁知道这里实际发生了什么;我只是在猜测。
它应该是在自己的线程上执行的webservice调用。然后你将利用完成处理程序(在主线程上)来解除任何需要解雇的UI元素。