0

我有一个名为“刷新数据”的UIBarButtonItem。当用户点击它时,应用程序应刷新其数据。点击该按钮时发生的事情是启动Web服务并引入xml数据,它们的订单为30000-40000条记录。所以为了防止UI挂起,我写了一个后台线程,并在那里加载。UIAlertview挂在后台线程正在加载数据

- (void)refreshDataAction 
{ 
NSLog(@"Refresh Data"); 
//Put up an alert box indicating user to wait while data is loading. 

UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Data is Loading" 
                 message:@"Please wait while data is being refreshed." 
                 delegate:self 
               cancelButtonTitle:@"OK" 
              otherButtonTitles:nil, nil]; 
alert.tag = 10; 
[alert show]; 
} 

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex 
{ 
NSLog(@"hit in clickedbuttonatindex alertview at 259"); 
self.refreshActIndicator.hidden = NO; 
[self.refreshActIndicator startAnimating]; 
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 
             (unsigned long)NULL), ^(void) { 
    [self getAllCustomerValues]; 

    NSError *nwerror = nil; 
    if (![self.secondMOC save:&nwerror]) 
    { 
     NSLog(@"209 Failed to save second MOC"); 
    } 
    else 
    { 
     //NSLog(@"saved success"); 
    } 
}); 
} 

就像你可以看到警报视图显示。我点击确定,该框仍然存在“变黑”,并挂在屏幕上。然后7-8秒后,该框消失,动画开始动画指示器。我的目标是得到这样的东西。 1.用户点击刷新数据按钮。 2.出现警告视图。 3.用户单击确定。 4.警告框消失,立即后台线程开始工作,我看到活动指示器工作/动画。

用户将知道在活动指示器动画时等待。那么,如何在用户点击“确定”后立即启动应用程序,并立即开始动画制作,并且alertview确定不会变黑。我清楚了吗?如果您需要更多信息,请询问。谢谢

编辑:这个屏幕有一个后台线程在它加载第一次当天的工作。这之前有一个屏幕。在它上面,我继续按钮,然后单击它,启动后台线程,这个线程完全相同,就像这个在这里一样。我不杀它或任何东西。

编辑2:

- (void)refreshDataAction 
    { 
NSLog(@"Refresh Data"); 
self.txtCustomerSearch.text [email protected]""; 
[self cleanUPPreviousLabels]; 

//Put up an alert box indicating user to wait while data is loading. 

UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Data is Loading" 
               message:@"Please wait while data is being refreshed." 
               delegate:self 
             cancelButtonTitle:@"OK" 
             otherButtonTitles:nil, nil]; 
//alert.tag = 10; 
//[alert show]; 
[alert performSelectorOnMainThread:@selector(show) withObject:nil waitUntilDone:FALSE]; 

NSLog(@"hit in willpresenet alertview at 221"); 
    self.refreshActIndicator.hidden = NO; 
    [self.refreshActIndicator startAnimating]; 
NSLog(@"Dispatching"); 

//Disable the view and all the other controls 
self.txtCustomerSearch.userInteractionEnabled =NO; 
self.txtCustomerSearch.enabled =NO; 
self.btnSearch.enabled =NO; 
self.btnSearch.userInteractionEnabled = NO; 
self.scrollView.userInteractionEnabled = NO; 
//self.view.userInteractionEnabled =NO; 
self.chkButton.enabled = NO; 


[self deletePreviousValues]; 

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ 
    NSLog(@"Getting customer values"); 
    [self getAllCustomerValues]; 
    NSLog(@"Got customer values"); 

    NSError *nwerror = nil; 
    if (![self.secondMOC save:&nwerror]) 
    { 
     NSLog(@"209 Failed to save second MOC"); 
    } 
    else 
    { 
     //NSLog(@"saved success"); 
    } 


    self.txtCustomerSearch.userInteractionEnabled = YES; 
    self.txtCustomerSearch.enabled =YES; 
    self.btnSearch.enabled =YES; 
    self.btnSearch.userInteractionEnabled = YES; 
    self.scrollView.userInteractionEnabled = YES; 
    self.view.userInteractionEnabled =YES; 
    self.chkButton.enabled = YES; 

    [self.refreshActIndicator stopAnimating]; 

    NSLog(@"Saved"); 


}); 
NSLog(@"Dispatched"); 

}

+0

getAllCustomerValues方法是否同步? – 2013-02-21 19:37:07

+0

@GeorgeSachin。我如何知道? – RookieAppler 2013-02-21 19:41:06

+0

@GeorgeSachin - 由于它在异步队列上执行,它将异步运行。 – rmaddy 2013-02-21 19:41:52

回答

0

尝试改变

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 
            (unsigned long)NULL), ^(void) { 

到后台优先

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 
            (unsigned long)NULL), ^(void) { 
+0

@ Ric.No。改变它,但它仍然是这样的。警告框变黑,7-8秒后它消失,然后我的活动指标动画开始。另外我编辑了我的原始文章中的一些信息。请检查一下。 – RookieAppler 2013-02-21 19:31:48

0

使用alertView:didDismissWithButtonIndex:,而不是alertView:clickedButtonAtIndex:。这样,当您的代码被调用时,警报已被解除。

问题 - 为什么要打扰警报视图?用户知道他们点击了“刷新”图标。您已经显示活动指示器,并且警报不会让用户有机会取消刷新。

更新:调用dispatch_async似乎有点关闭。试试这个:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
    [self getAllCustomerValues]; 

    NSError *nwerror = nil; 
    if (![self.secondMOC save:&nwerror]) { 
     NSLog(@"209 Failed to save second MOC"); 
    } else { 
     //NSLog(@"saved success"); 
    } 
}); 
+0

那么,当我没有警报视图,然后点击刷新按钮,它仍然需要7-8秒来显示活动指标。所以屏幕冻结了7-8秒没有发生任何事情。没有指示器。没有。我不知道为什么它会花费那么多时间。但是现在我介绍了警报视图,告诉他们事情正在发生。 – RookieAppler 2013-02-21 19:44:38

+0

您所描述的内容表明数据加载('getAllCustomerValues')确实在主线程上运行。但是,由于您正在后台队列上运行该代码,因此情况并非如此。看到我更新的答案。 – rmaddy 2013-02-21 19:48:21

+0

我改变了你的建议。 dismissWithButtonIndex并在dispatch_async中更改。但只有它那样。我点击刷新数据。警报视图打开。点击确定关闭。警报框消失了。延迟7-8秒(没有任何反应),然后指示器开始旋转/动画。 – RookieAppler 2013-02-21 19:58:48

0

它可能有助于添加一些NSLogs来查看它挂起的位置并停止活动指示器以查看是否因分派而发生整个挂起。

NSLog(@"hit in clickedbuttonatindex alertview at 259"); 
self.refreshActIndicator.hidden = NO; 
[self.refreshActIndicator startAnimating]; 
NSLog(@"Dispatching"); 
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 
            (unsigned long)NULL), ^(void) { 
    NSLog(@"Getting customer values"); 
    [self getAllCustomerValues]; 
    NSLog(@"Got customer values"); 

    NSError *nwerror = nil; 
    if (![self.secondMOC save:&nwerror]) 
    { 
     NSLog(@"209 Failed to save second MOC"); 
    } 
    else 
    { 
     //NSLog(@"saved success"); 
    } 
    [self.refreshActIndicator stopAnimating]; 
    NSLog(@"Saved"); 
}); 
NSLog(@"Dispatched"); 

发生什么情况是主要(UI)队列由于某种原因而停止,这会导致东西似乎挂起。因为它已停止,所以即使您已告诉他们开始动画,刷新活动指示器等动画也不会生成动画。并且请记住,您无法在async中更新UI,因此不应使用secondMOC来使任何表重新载入数据和[self getAllCustomerValues];不应该做任何UI的东西。

+0

所以在模拟器上的输出是:点击clicktonbuttonatindex alertview在259.Dispatching.Getting顾客values.Dispatched.Got顾客values.Saved。在模拟器上也没有延迟(没有7-8秒的等待)。在设备上需要时间。 – RookieAppler 2013-02-21 20:08:22

+0

当您在设备上进行调试时 - “在iOS设备上运行” - 输出结果如何? – Ric 2013-02-21 20:12:10

+0

当我连接我的设备到Mac,在xcode我得到“Phani的iPad,iPad 6.1模拟器,iPhone 6.1模拟器”。我选择“phani的ipad”,然后运行,然后在Xcode中看不到任何输出。你在说什么?你能解释一下吗?谢谢 – RookieAppler 2013-02-21 20:21:19

0

我们使用MBProgressHUD(https://github.com/jdg/MBProgressHUD),这使得这种UI通知变得简单。一般来说,你提供了一个被调用的方法,可以检查一个原子布尔值。放置HUD时设置BOOL,当后台进程完成时清除BOOL,HUD将自动消失。

0

你说这一切发生在后台线程 - 确保您加载主线程上UIAlertView中:

//[alert show]; 
[alert performSelectorOnMainThread:@selector(show) withObject:nil waitUntilDone:FALSE]; 

这可能会解决这个问题。您的异步调用实际上是在运行循环中的当前线程上发生的(因为它是后台线程),阻止您试图显示的警报视图(在同一个运行循环中)。

+0

我像你说的那样编辑我的代码。它没有工作。我已经发布了refreshDataAction修改方法。看看并告诉我,如果你发现任何错误。谢谢 – RookieAppler 2013-02-22 00:08:46