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

时间:2022-07-16 03:59:05

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,因为我的应用程序会立即获取一些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

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在数据显示并显示后解散。我可以在世界上如何启用一种方法来停止所有这些并返回(空白)界面? GestureRecognizer?我会在MBProgressHUD类中设置它吗?太沮丧......

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

衷心感谢任何帮助。我为长篇大论道歉。而对于我丑陋的代码......

3 个解决方案

#1


35  

No need to extend MBProgressHUD. Simply add an UITapGestureRecognizer to 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.
}

#2


5  

The MBProgressHUD is 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 theMBProgressHUD and act accordingly.

您必须将视图控制器设置为MBProgressHUD的委托并相应地执行操作。

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

如果您需要更多澄清,请告诉我:)

#3


0  

To have extra information:

要获得额外信息:

  1. You could create contentView in your view
  2. 您可以在视图中创建contentView
  3. And simply show the hud in your contentView (not in your self.view or self.navigationController.view)
  4. 只需在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.

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

#1


35  

No need to extend MBProgressHUD. Simply add an UITapGestureRecognizer to 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.
}

#2


5  

The MBProgressHUD is 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 theMBProgressHUD and act accordingly.

您必须将视图控制器设置为MBProgressHUD的委托并相应地执行操作。

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

如果您需要更多澄清,请告诉我:)

#3


0  

To have extra information:

要获得额外信息:

  1. You could create contentView in your view
  2. 您可以在视图中创建contentView
  3. And simply show the hud in your contentView (not in your self.view or self.navigationController.view)
  4. 只需在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.

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