在我的项目中,每个用户交互事件都进行网络调用(即TCP,而不是HTTP)。我需要将活动指标从全局变为显示来自UIViewController
隐藏来自NetworkActivityManager
类(用于处理网络活动的自定义类,其中不是UIViewController或UIView的子类。
搜索网页后,我发现 MBProgressHUD 用于同一目的,但我无法找到一个关于如何全局使用它的示例。 (通过说全局我的意思是 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
Class:
[MBProgressHUD hideHUDForView:appDelegate.navigationController.topViewController.view animated:YES];
这会使项目在一段时间后崩溃(由于内存问题。) 我在我的项目中使用ARC,而且,我正在使用ARC版本的 MBProgressHUD 。
我错过了什么吗?
重要问题:
我可以让 MBProgressHUD 像UIAlertView一样工作吗? (说我的意思是 MBProgressHUD 的实现独立于UIView - 它使用showHUDAddedTo:
来呈现自己)???
请注意:在上面隐藏MBProgressHUD的代码中,View可能会与显示MBProgressHUD时的内容有所不同。
非常感谢任何帮助。
答案 0 :(得分:66)
您可以将此添加到您喜欢的课程中:
+ (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];
}
这可以在任何课程上调用。使用这些类方便方法时,您无需对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;
}
答案 1 :(得分:7)
与许多iOS问题一样,现在已经完全过时了。
这些天你当然只是使用了一个微不足道的
对于这样的任何问题。
初学者的完整容器视图教程.. tutorial!
MBProgressHUD是当天的一个奇迹般的解决方案,因为它有一个很大的漏洞"在Apple的管道中。
但是(和过去许多精彩的东西一样),现在只是历史。今天不要这样做。
Just 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]; });
}];
}
);
}
方便的宏..
#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
答案 2 :(得分:3)
This回答是我现在用于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。
答案 3 :(得分:2)
我发现@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)
}
上面的代码放在一个全局文件中,我保留了所有的全局帮助器和常量。
答案 4 :(得分:1)
我用过它如下..希望它可以帮助你......
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];
答案 5 :(得分:1)
注意:考虑到这个问题的观点,我决定发布我选择作为解决方案的方式。 这不是我的问题的答案。(因此,接受的答案仍然被接受)
当时我最终使用SVProgressHUD,因为它非常易于集成和使用。
您只需将SVProgressHUD / SVProgressHUD文件夹拖到项目中即可。 (你可以选择去cocoapods或迦太基)
在Objective-C中:
[SVProgressHUD show]; // Show
[SVProgressHUD dismiss]; // Dismiss
在Swift中:
SVProgressHUD.show() // Show
SVProgressHUD.dismiss() // Dismiss
此外,显示和隐藏HUD需要在主线程上执行。 (具体来说,你需要这个来隐藏背景中某些闭包的HUD)
<强> e.g:强>
dispatch_async(dispatch_get_main_queue(), ^{
[SVProgressHUD dismiss]; // OR SHOW, whatever the need is.
});
还有其他方法可以显示带有HUD的自定义消息,显示短时间内的成功/失败以及自动关闭。
MBProgressHUD 仍然是开发人员的不错选择。只是我找到 SVProgressHUD 来满足我的需求。
答案 6 :(得分:0)
添加这两种方法以在单件类中显示或隐藏加载器
- (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];
}
答案 7 :(得分:0)
我使用的是@Michael Shang的代码,并且在显示HUD时出现各种不一致的行为。原来使用最后一个窗口是不可靠的,因为iOS键盘可能只是隐藏它。所以在大多数情况下,你应该使用@David Lawson提到的AppDelegate来获取窗口。
以下是Swift中的内容:
let window = UIApplication.sharedApplication().delegate!.window!!
let hud = MBProgressHUD.showHUDAddedTo(window, animated: true)
然而,有了上述内容,您的HUD将显示在iOS键盘后面(如果它们重叠)。如果您需要HUD覆盖键盘,请使用最后一个窗口方法。
在我的情况下,发生的事情是我会显示HUD,然后立即调用resignFirstResponder()
隐藏添加HUD的窗口。所以这是需要注意的事项,唯一可以保留的窗口是第一个。
我最终创建了一个方法,如果需要,可以选择在键盘上方添加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
}
答案 8 :(得分:0)
要一次显示一个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];
});
}