当 JSON 调用时间过长时允许用户取消 MBProgressHUD

Posted

技术标签:

【中文标题】当 JSON 调用时间过长时允许用户取消 MBProgressHUD【英文标题】:Allow User to Cancel MBProgressHUD when JSON call takes too long 【发布时间】:2012-11-03 19:01:53 【问题描述】:

我已经阅读并阅读了有关此内容的 SO,但我似乎找不到任何符合我情况的内容。

当视图出现时,我已经加载了 MBProgressHUD,因为我的应用程序会立即获取一些 Web 服务数据。我的问题是我的导航控制器上的后退按钮在显示 HUD 时没有响应(因此在应用程序获取其数据时)。我希望用户能够点击关闭(或者在最坏的情况下能够点击后退按钮)以摆脱困境,如果这是一个无休止的等待。这是我在视图出现后立即运行的代码:

#ifdef __BLOCKS__
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.navigationController.view animated:YES];
hud.labelText = @"Loading";
hud.dimBackground = NO;
hud.userInteractionEnabled = YES;

dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_LOW, 0), ^
    // Do a task in the background
    NSString *strURL = @"http://WEBSERVICE_URL_HERE";

    //All the usual stuff to get the data from the service in here

    NSDictionary* responseDict = [json objectForKey:@"data"]; // Get the dictionary
    NSArray* resultsArray = [responseDict objectForKey:@"key"]; 


    // Hide the HUD in the main tread
    dispatch_async(dispatch_get_main_queue(), ^

        for (NSDictionary* internalDict in resultsArray) 
        
            for (NSString *key in [internalDict allKeys]) 
            //Parse everything and display the results
            

        

        [MBProgressHUD hideHUDForView:self.navigationController.view animated:YES];
    );
); 
#endif

省略所有关于解析 JSON 的废话。这一切都很好,HUD 在数据出现并显示后消失。在世界上我怎样才能启用一种方法来停止所有这一切并返回(空白)界面?手势识别器?我会在 MBProgressHUD 类中设置它吗?好郁闷……

非常感谢您的帮助。我为这篇长文道歉。而对于我丑陋的代码......

【问题讨论】:

【参考方案1】:

无需扩展MBProgressHUD。只需添加一个UITapGestureRecognizer 即可。

ViewDidLoad

MBProgressHUD *HUD = [MBProgressHUD showHUDAddedTo:self.view animated:NO];
HUD.mode = MBProgressHUDModeAnnularDeterminate;

UITapGestureRecognizer *HUDSingleTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(singleTap:)];
[HUD addGestureRecognizer:HUDSingleTap];

然后:

-(void)singleTap:(UITapGestureRecognizer*)sender

      //do what you need.

【讨论】:

【参考方案2】:

MBProgressHUD 只是一个带有自定义绘图以指示当前进度的视图,这意味着它不负责您应用的任何逻辑。如果你有一个长时间运行的操作需要在某个时候取消,你必须自己实现。

最优雅的解决方案是扩展MBProgressHUD。您可以绘制一个充当按钮角色的自定义区域,以编程方式添加一个按钮,或者只是等待整个视图上的点击事件。然后,您可以在点击该按钮或视图时调用委托方法。

它可能看起来像这样:

 // MBProgressHUD.h
 @protocol MBProgressHUDDelegate <NSObject>
 - (void)hudViewWasTapped; // or any other name 
 @end

// MBProgressHUD.m
// Either this, or some selector you set up for a gesture recognizer
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 
    if ([self.delegate respondsToSelector:@selector(hudViewWasTapped)]) 
        [self.delegate performSelector:@selector(hudViewWasTapped)];
    

您必须将您的视图控制器设置为MBProgressHUD 的委托并采取相应措施。

如果您需要对此进行更多说明,请告诉我 :)

【讨论】:

一个问题,如果父视图触摸它也会调用【参考方案3】:

要获得更多信息:

    您可以在视图中创建 contentView 只需在您的 contentView 中显示 hud (而不是在您的 self.view 或 self.navigationController.view 中)

这样,您的navigationBar 的视图将不对您的hudView 负责。因此,您可以从 navigationController 的视图返回到上一页。

【讨论】:

以上是关于当 JSON 调用时间过长时允许用户取消 MBProgressHUD的主要内容,如果未能解决你的问题,请参考以下文章

是否可以使用 iBATIS 中止长时间运行的查询?

当用户关闭浏览器等待长时间运行的 Web 服务调用时会发生啥?

如何取消 AJAX 长时间运行的 MVC 动作客户端(在 javascript 中)?

多线程之取消架构

进入后台时的 NSURLConnection 最佳实践

CancellationToken 永远不会取消我长时间运行的加载数据功能