UIAlertview挂起,而后台的线程正在加载数据

时间:2013-02-21 19:17:36

标签: ios animation uialertview uiactivityindicatorview

我有一个名为“刷新数据”的UIBarButtonItem。当用户单击它时,应用程序应刷新其数据。在该按钮单击上发生的是启动Web服务并带来xml数据,它们的订单数量为30000-40000。因此,为了防止UI挂起,我写了一个后台线程并在那里加载。

- (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.Alert视图显示。 3.用户单击确定。 4.Alert框消失,后台线程立即开始工作,我看到活动指示器工作/动画。

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

编辑:当第一次加载当天时,此屏幕有一个后台线程正在处理它。在此之前有一个屏幕。在它上面我有继续按钮并点击它启动背景线程,它完全像这一样在这里。我不会杀死它或任何东西。

编辑2:

 - (void)refreshDataAction
   {
NSLog(@"Refresh Data");
self.txtCustomerSearch.text =@"";
[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");

}

5 个答案:

答案 0 :(得分: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) {

答案 1 :(得分: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");
    }
});

答案 2 :(得分:0)

添加一些NSLog可能有助于查看它挂起的位置,并停止活动指示器以查看是否由于调度而导致整个挂起。

 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)队列由于某种原因而被停止,这导致事物看起来挂起。因为它已停止,即使您已告诉他们开始设置动画,刷新活动指示器等内容也不会生成动画。并且请记住,您无法在异步中更新UI,因此不应使用secondMOC来导致任何表重新加载数据和[self getAllCustomerValues];不应该做任何UI的东西。

答案 3 :(得分:0)

我们使用MBProgressHUD(https://github.com/jdg/MBProgressHUD),这使得这种UI通知变得容易。通常,您提供一个可以检查 atomic BOOL值的方法。当您放置HUD时设置BOOL,当后台进程完成时清除BOOL并且HUD将自动消失。

答案 4 :(得分:0)

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

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

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

相关问题