iOS 8中的NSThread detachNewThreadSelector

iOS 8中的NSThread detachNewThreadSelector,ios,objective-c,iphone,multithreading,Ios,Objective C,Iphone,Multithreading,该应用程序在iOS 7中正常工作,但当我切换到iOS 8时,该应用程序的工作方式与预期不同。在调试模式下,会调用应用程序中的NSThread detachNewThreadSelector函数在前台创建一个忙框,以阻止用户访问。主线程继续并调用web服务来检索数据。一旦接收到数据,就会调用另一个detachNewThreadSelector来关闭第一个线程 在iOS 8中,当我在调试模式下单步执行时,在到达detachNewThreadSelector之后,什么也没有发生。第一个线程中的代码未执

该应用程序在iOS 7中正常工作,但当我切换到iOS 8时,该应用程序的工作方式与预期不同。在调试模式下,会调用应用程序中的NSThread detachNewThreadSelector函数在前台创建一个忙框,以阻止用户访问。主线程继续并调用web服务来检索数据。一旦接收到数据,就会调用另一个detachNewThreadSelector来关闭第一个线程

在iOS 8中,当我在调试模式下单步执行时,在到达detachNewThreadSelector之后,什么也没有发生。第一个线程中的代码未执行。主线程继续打开并调用web服务来检索数据。一旦接收到数据,第二个detachNewThreadSelector将到达,但代码在到达viewdidload函数的末尾之前不会执行

dismissActivityIndicator的代码在CFRUNLOOP\u is\u调用\u OUT\u到\u SOURCE0\u PERFORM\u函数中执行,该函数将生成“尝试从视图控制器中解除”错误。然后,它进入_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];
}
主线程继续并调用web服务来检索数据

我不熟悉如何生成弹出视图来阻止主线程,直到从源获取数据

不要在主线程上做这种事情!如果您仅将主线程用于UI,而绝对不会用于需要等待其他内容的任何内容,那么这样的问题就会自行解决

你也在做
睡眠(1),由于类似的原因,它是坏的。此外,您几乎不需要使用适当设计的
睡眠
。使用
sleep
可以很好地说明您不了解线程

现在开始回答(可能)

我很难理解为什么要将
showActivityIndicator
dismissActivityIndicator
分离到它们自己的线程。除主线程以外的任何对象上的UI操作通常不仅是未定义的行为(不是线程安全的),而且通常是一个坏主意

其次,将它们分离到不同的线程,以便它们同时运行。显然这不是你想要的。
dismissActivityIndicator
需要在webservice调用返回之后而不是之前运行。您从代码中删除了
showActivityIndicator
dismissActivityIndicator
之间的实际调用,因此谁知道这里到底发生了什么;我只是在猜测


它应该是在自己的线程上执行的webservice调用。然后,您将利用完成处理程序(在主线程上)来消除任何需要消除的UI元素。

此函数是一个更新函数,它调用应用程序正常运行所必需的数据。这就是为什么主线程在收到数据之前被阻塞的原因。@vily这不是阻塞主线程的好理由。我想不出任何理由阻止主线程。主要功能是同时运行showActivityIndicator和主线程,直到检索到大量数据,dismissActivityIndicator将在web服务调用完成后删除第一个线程,以使应用程序可用,这在iOS 7中工作。此函数是一个初始化/更新函数。在数据初始化之前,应用程序将无法工作;如果在工作日开始时未进行更新,则不会显示正确的数据。现在必须这么做的原因是因为该应用程序是在没有互联网连接的地方使用的available@vily我保证我理解这一切;你仍然在以完全错误的方式行事。从后台线程执行UI操作时总会遇到问题,阻止主线程始终是个坏主意。故事结束了。显然你不相信我,但我已经尽力说服你了。祝你好运尝试解决你的问题,打破线程的基本原则。我同意你说的,但我没有时间正确重写应用程序。我正在使用iOS 8的黑客程序。调度队列后台队列=调度获取全局队列(调度队列优先级默认为空);dispatch_async(后台_queue,^{//在这里做一些需要很长时间的事情…[self showActivityIndicator];//在主队列上跟进一些事情dispatch_async(dispatch_get_main_queue(),^{//通常更新主线程上的UI。});});适用于iOS 8,但不适用于iOS 7。我正在使用一个条件