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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13212467/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 02:00:45  来源:igfitidea点击:

Allow User to Cancel MBProgressHUD when JSON call takes too long

iosxcodejsonuigesturerecognizermbprogresshud

提问by gummo

I've read and read on SO about this, and I just can't seem to find anything that matches my situation.

我已经阅读并阅读了关于此的内容,但我似乎无法找到与我的情况相符的任何内容。

I've got MBProgressHUD loading when the view appears, as my app immediately goes to grab some webservice data. My problem is the back button on my navigationcontroller is unresponsive while the HUD is displayed (and therefore while the app gets its data). I want the user to be able to tap to dismiss (or to be able to hit the back button in the worst case) to get the heck out, if it's an endless wait. Here's my code that runs as soon as the view appears:

当视图出现时,我已经加载了 MBProgressHUD,因为我的应用程序会立即获取一些网络服务数据。我的问题是我的导航控制器上的后退按钮在显示 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

Leaving out all the gibberish about parsing the JSON. This all works fine, and the HUD dismisses after the data shows up and gets displayed. How in the world can I enable a way to stop all this on a tap and get back to the (blank) interface? GestureRecognizer? Would I set that up in the MBProgressHUD class? So frustrated...

省略所有关于解析 JSON 的胡言乱语。这一切正常,并且在数据出现并显示后 HUD 会消失。我到底如何才能启用一种方法来停止所有这一切并返回(空白)界面?手势识别器?我会在 MBProgressHUD 类中设置它吗?好沮丧...

Kindest thanks for any help. My apologies for the long post. And for my ugly code...

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

回答by Piotr Tomasik

No need to extend MBProgressHUD. Simply add an UITapGestureRecognizerto it.

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

ViewDidLoad:

ViewDidLoad:

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

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

And then:

进而:

-(void)singleTap:(UITapGestureRecognizer*)sender
{
      //do what you need.
}

回答by iska

The MBProgressHUDis just a view with a custom drawing to indicate the current progress, which means it is not responsible for any of your app's logic. If you have a long running operation which needs to be canceled at some point, you have to implement this yourself.

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

The most elegant solution is to extend the MBProgressHUD. You can either draw a custom area which plays the role of a button, add a button programmatically or just wait for a tap event on the whole view. Then you can call a delegate method whenever that button or the view is tapped.

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

It can look like this:

它看起来像这样:

 // 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)];
    }
}

you have to set your view controller as the delegate for theMBProgressHUDand act accordingly.

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

Let me know if you need more clarification on this :)

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

回答by Ahmet Kazim Günay

To have extra information:

要获得额外信息:

  1. You could create contentView in your view
  2. And simply show the hud in your contentView (not in your self.view or self.navigationController.view)
  1. 您可以在视图中创建 contentView
  2. 只需在您的 contentView 中显示hud(而不是在您的 self.view 或 self.navigationController.view 中)

in this way your navigationBar's view will not be responsible for your hudView. So, you can go back from your navigationController's view to previous page.

这样,您的导航栏视图将不对您的 hudView 负责。因此,您可以从导航控制器的视图返回到上一页。