全球使用MBProgressHUD +使其成为单身人士

在我的项目中,每个用户交互事件都会进行networking调用(即TCP,而不是HTTP)。 我需要活动指标是全局的,以显示从随机UIViewController隐藏NetworkActivityManager类(处理networking活动,这不是UIViewController或UIView的子类的自定义类) 隐藏

在search网页后,我发现MBProgressHUD用于同样的目的,但我无法find一个关于如何在全球范围内使用它的例子。 (通过说全局我是指MBProgressHUD的单例对象和类方法来显示和隐藏它。)

以下是我已经尝试过,但失败了:在AppDelegate.h:

@property (nonatomic, retain) MBProgressHUD *hud;

AppDelegate.m中:

@synthesize hud;

在一些随机的UIViewController对象中:

 appDelegate.hud = [MBProgressHUD showHUDAddedTo:appDelegate.navigationController.topViewController.view animated:YES]; appDelegate.hud.labelText = @"This will take some time."; 

在隐藏它的时候,从NetworkActivityManager类:

 [MBProgressHUD hideHUDForView:appDelegate.navigationController.topViewController.view animated:YES]; 

这使得项目在一段时间后崩溃(由于内存问题)。我在我的项目中使用ARC,并且还使用ARC版本的MBProgressHUD

我错过了什么吗?

重要问题:

我可以让MBProgressHUD像UIAlertView 一样工作吗? (说我的意思是独立于UIView的MBProgressHUD的实现 – 它使用showHUDAddedTo:呈现自己)?

请注意:在隐藏MBProgressHUD的上述代码中,View可能与显示MBProgressHUD时的内容有所不同。

任何帮助不胜感激。

你可以把它添加到你喜欢的类中:

 + (MBProgressHUD *)showGlobalProgressHUDWithTitle:(NSString *)title { UIWindow *window = [[[UIApplication sharedApplication] windows] lastObject]; MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:window animated:YES]; hud.labelText = title; return hud; } + (void)dismissGlobalHUD { UIWindow *window = [[[UIApplication sharedApplication] windows] lastObject]; [MBProgressHUD hideHUDForView:window animated:YES]; } 

这可以比任何一个class都要求。 使用这些便利的方法时,您不需要强调HUD。

根据您的具体情况,您可能还需要处理在另一个隐藏之前请求新的hud的情况。 你可以在新来的时候隐藏以前的hud,或者想出某种排队等等。

在显示新的HUD之前隐藏以前的HUD实例非常简单。

 + (MBProgressHUD *)showGlobalProgressHUDWithTitle:(NSString *)title { UIWindow *window = [[[UIApplication sharedApplication] windows] lastObject]; [MBProgressHUD hideAllHUDsForView:window animated:YES]; MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:window animated:YES]; hud.labelText = title; return hud; } 

注意…

与许多iOS问题一样,现在已经完全过时了。

这些日子,你当然只是使用一个微不足道的

容器视图

对于这样的任何问题。

完整的容器视图教程初学者.. 教程!

MBProgressHUD是当天的奇迹般的解决scheme,因为苹果公司正在制造一个“严重的漏洞”。

但是(就像过去的许多美妙的事物一样),这只是现在的历史。 今天不要做这样的事情


只是FWIW,2014,这是我们使用的一个非常简单的设置。 Per David Lawson …

 UIWindow *window = [[UIApplication sharedApplication] delegate].window 

正如Matej所说,只需使用AppDelegate …

 #define APP ((AppDelegate *)[[UIApplication sharedApplication] delegate]) 

AppDelegate.h

 // our convenient huddie system (messages with a hud, spinner) @property (nonatomic, strong) MBProgressHUD *hud; -(void)huddie; 

AppDelegate.m

 -(void)huddie { // centralised location for MBProgressHUD [self.hud hide:YES]; UIWindow *windowForHud = [[UIApplication sharedApplication] delegate].window; self.hud = [MBProgressHUD showHUDAddedTo:windowForHud animated:YES]; self.hud.dimBackground = YES; self.hud.minShowTime = 0.1; self.hud.labelText = @""; self.hud.detailsLabelText = @""; } 

在您使用的代码中设置标题 – 因为在运行过程中经常更改它们 。 (“步骤1”…“步骤2”等)

 -(void)loadBlahFromCloud { [APP huddie]; APP.hud.labelText = @"Connecting to Parse..."; APP.hud.detailsLabelText = @"step 1/2"; [blah refreshFromCloudThen: ^{ [... example]; }]; } -(void)example { APP.hud.labelText = @"Connecting to the bank..."; APP.hud.detailsLabelText = @"step 2/2"; [blah sendDetailsThen: ^{ [APP.hud hide:YES]; [... showNewDisplay]; }]; } 

如果你愿意的话,可以把文章作为参数来改变

你总是希望self.hud.minShowTime = 0.1; 避免闪烁

几乎总是self.hud.dimBackground = YES; 这也阻止用户界面

从概念上讲,当你提出这样一个过程时, 通常不得不“稍微等待”开始工作/结束工作 ,就像使用UI进行类似的编程一样。

所以在实践中,代码通常看起来像这样…

 -(void)loadActionSheets { [APP huddie]; APP.hud.labelText = @"Loading json from net..."; dispatch_after_secs_on_main(0.1 , ^{ [STUBS refreshNowFromCloudThen: ^{ [APP.hud hide:YES]; dispatch_after_secs_on_main(0.1 , ^{ [self buildActionsheet]; }); }]; } ); } 

方便的macros..

 #define dispatch_after_secs_on_main( SS, BB ) \ dispatch_after( \ dispatch_time(DISPATCH_TIME_NOW, SS*NSEC_PER_SEC), \ dispatch_get_main_queue(), \ BB \ ) 

这是现在所有的历史:) https://stackoverflow.com/a/23403979/294884

这个答案是我现在正在使用的5-6个应用程序,因为它在块内部也是完美的。 但是我发现它有一个问题。 我可以让它显示,但是不能让它消失,如果UIAlertView也存在。 如果你看看实现,你可以看到为什么。 只需将其更改为:

 static UIWindow *window; + (MBProgressHUD *)showGlobalProgressHUDWithTitle:(NSString *)title { window = [[[UIApplication sharedApplication] windows] lastObject]; MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:window animated:YES]; hud.labelText = title; return hud; } + (void)dismissGlobalHUD { [MBProgressHUD hideHUDForView:window animated:YES]; } 

这将确保您从显示的窗口中移除HUD。

我发现@Matej Bukovinski的回答非常有帮助,因为我刚开始使用Swift,我的目的是使用他的方法为MBProgressHUD设置一个全局字体,我已经将代码转换为swift,并愿意分享下面的代码:

 class func showGlobalProgressHUDWithTitle(title: String) -> MBProgressHUD{ let window:UIWindow = UIApplication.sharedApplication().windows.last as! UIWindow let hud = MBProgressHUD.showHUDAddedTo(window, animated: true) hud.labelText = title hud.labelFont = UIFont(name: FONT_NAME, size: 15.0) return hud } class func dismissGlobalHUD() -> Void{ let window:UIWindow = UIApplication.sharedApplication().windows.last as! UIWindow MBProgressHUD.hideAllHUDsForView(window, animated: true) } 

上面的代码放在一个全局文件中,我保留了所有的全局帮助器和常量。

我用它如下..希望它可以帮助你..

appDelegate.m

 -(void)showIndicator:(NSString *)withTitleString currentView:(UIView *)currentView { if (!isIndicatorStarted) { // The hud will dispable all input on the view self.progressHUD = [[[MBProgressHUD alloc] initWithView:currentView] autorelease]; // Add HUD to screen [currentView addSubview:self.progressHUD]; self.progressHUD.labelText = withTitleString; [window setUserInteractionEnabled:FALSE]; [self.progressHUD show:YES]; isIndicatorStarted = TRUE; } } -(void)hideIndicator { [self.progressHUD show:NO]; [self.progressHUD removeFromSuperview]; self.progressHUD = nil; [window setUserInteractionEnabled:TRUE]; isIndicatorStarted = FALSE; } 

从随机视图:

[appDel showIndicator:@"Loading.." currentView:presentView.view];

:考虑到这个问题的意见越来越大,我决定发布我select的解决scheme。 这不是我的问题的答案。 (因此,接受的答案仍然被接受)

那时我最终使用了SVProgressHUD,因为它很容易集成和使用。

您只需将SVProgressHUD / SVProgressHUD文件夹拖到您的项目中即可。 (你也可以select去cocoapods或迦太基)


在Objective-C中:

 [SVProgressHUD show]; // Show [SVProgressHUD dismiss]; // Dismiss 

在Swift中:

 SVProgressHUD.show() // Show SVProgressHUD.dismiss() // Dismiss 

另外,显示和隐藏HUD需要在主线程上执行 。 (具体来说,你需要这个隐藏在后台的一些封闭的HUD)

例如:

 dispatch_async(dispatch_get_main_queue(), ^{ [SVProgressHUD dismiss]; // OR SHOW, whatever the need is. }); 

还有其他方法可以用HUD显示自定义消息,显示短时间成功/失败和自动退出。

MBProgressHUD仍然是开发者的不错select。 这只是我发现SVProgressHUD,以满足我的需求。

添加这两个方法来显示或隐藏你的单例类的加载器

 - (void)startLoaderWithText:(NSString *)title View:(UIView *)view{ progressHud = [MBProgressHUD showHUDAddedTo:view animated:YES]; progressHud.labelText = title; progressHud.activityIndicatorColor = [UIColor grayColor]; progressHud.color = [UIColor clearColor]; [progressHud show:YES]; } - (void)stopLoader{ [progressHud hide:YES]; } 

我正在使用@Michael Shang的代码,并且在显示HUD时出现各种不一致的行为。 因为iOS键盘可能只是隐藏它,所以使用最后一个窗口是不可靠的。 所以在大多数情况下,您应该使用@David Lawson所提到的AppDelegate来获取窗口。

Swift中的方法如下:

 let window = UIApplication.sharedApplication().delegate!.window!! let hud = MBProgressHUD.showHUDAddedTo(window, animated: true) 

但是,在上述情况下,您的HUD将出现在iOS键盘后面(如果它们重叠)。 如果你需要你的平视显示器覆盖键盘使用最后一个窗口的方法。

在我的情况下,发生了什么事是我会显示HUD,然后调用resignFirstResponder()立即隐藏HUD被添加到窗口。 所以这是要注意的事情,唯一保证坚持的窗口是第一个。

我最终创build了一个方法,可以根据需要在键盘上方添加HUD。

 func createHUD(size: CGSize, overKeyboard: Bool = false) -> MBProgressHUD { let window = overKeyboard ? UIApplication.sharedApplication().windows.last! : UIApplication.sharedApplication().delegate!.window!! let hud = MBProgressHUD.showHUDAddedTo(window, animated: true) hud.minSize = size hud.bezelView.style = .SolidColor hud.bezelView.color = UIColor(white: 0, alpha: 0.8) return hud } 

要一次显示一个MBProgressHUD ,您可以检查天气HUD是否已添加到相同的视图中。 如果没有,则添加HUD,否则不要添加新的HUD。

 -(void)showLoader{ dispatch_async(dispatch_get_main_queue(), ^{ BOOL isHudAlreadyAdded = false; UIWindow *window = [[[UIApplication sharedApplication] windows] lastObject]; NSEnumerator *subviewsEnum = [window.subviews reverseObjectEnumerator]; for (UIView *subview in subviewsEnum) { if ([subview isKindOfClass:[MBProgressHUD class]]) { isHudAlreadyAdded = true; } } if(isHudAlreadyAdded == false){ [MBProgressHUD showHUDAddedTo:window animated:YES]; } }); } -(void)hideLoader{ dispatch_async(dispatch_get_main_queue(), ^{ UIWindow *window = [[[UIApplication sharedApplication] windows] lastObject]; [MBProgressHUD hideHUDForView:window animated:YES]; }); }