iOS 8中的NSThread detachNewThreadSelector

时间:2014-11-05 22:55:48

标签: ios objective-c iphone multithreading

该应用程序在iOS 7中正常运行,但当我疯狂切换到iOS 8时,该应用程序并没有像它想象的那样工作。在调试模式下,应用程序中的NSThread detachNewThreadSelector函数被调用以在前台创建一个忙盒以防止用户访问。主线程继续并调用Web服务来检索数据。一旦收到数据,就会调用另一个detachNewThreadSelector来关闭第一个线程。

在iOS 8中,当我在调试模式中单步执行时,在到达detachNewThreadSelector后,没有任何反应。第一个线程中的代码不会被执行。主线程继续打开并调用Web服务来检索数据。一旦接收到数据,就会到达第二个detachNewThreadSelector,但代码也不会被执行,直到它到达viewdidload函数的末尾。

dismissActivityIndi​​cator的代码在CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION中执行,该代码将生成“从视图控制器中解除”的尝试'错误。然后它进入__CFRunLoopDoSources0,然后在__CFRunLoopRun中执行showActivityIndi​​cator的代码。这会导致应用程序创建一个忙碌的框,因为dismissActivityIndi​​cator已经被执行,所以无法将其关闭。不确定为什么在反向和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];
}

1 个答案:

答案 0 :(得分:2)

  

主线程继续并调用Web服务来检索数据

     

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

不要在主线程上做这些事情!如果你只为UI使用主线程,那么像这样的问题就解决了。当然,对于任何不得不等待其他东西的事情都不会。

你也在(大概)主线程上做了sleep(1);,由于类似的原因这很糟糕。此外,您几乎不需要使用sleep进行适当的设计。使用sleep是一个很好的指标,你不懂线程。

现在回答(可能)

我很难理解为什么要将showActivityIndicatordismissActivityIndicator分离到自己的主题。除了主线程之外的任何操作的UI操作通常不仅是未定义的行为(不是线程安全的),而且通常是一个坏主意。

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

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