0

我有一个名为“刷新数据”的 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.警报视图出现。3.用户点击确定。4.警报框消失,后台线程立即开始工作,我看到活动指示器工作/动画。

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

编辑:该屏幕在当天第一次加载时有一个后台线程在运行。在此之前有一个屏幕。在它上面我有继续按钮并单击它启动后台线程,它与这里的这个完全一样。我不会杀死它或任何东西。

编辑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");

}

4

5 回答 5

0

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

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

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

于 2013-02-21T23:49:50.347 回答
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");
    }
});
于 2013-02-21T19:40:32.697 回答
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 的东西。

于 2013-02-21T19:55:41.367 回答
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) {
于 2013-02-21T19:22:12.243 回答
0

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

于 2013-02-21T20:24:49.353 回答