iphone ios singleton mbprogresshud

iphone - El uso de MBProgressHUD Globally+lo hace singleton



ios (9)

NOTA...

Al igual que con muchos problemas de iOS, esto ahora es drásticamente, totalmente desactualizado.

En estos días ciertamente solo usas un trivial.

Vista de contenedor

para cualquier problema como este.

Ver tutorial completo para principiantes .. tutorial!

MBProgressHUD fue una solución milagrosa en el pasado, porque había un "agujero drástico" en la tubería de Apple.

Pero (como con muchas cosas maravillosas del pasado), esto es solo historia ahora. No hagas nada como esto hoy.

Solo FWIW, 2014, aquí tenemos una configuración muy simple que usamos. Per David Lawson ...

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

como dice Matej, solo usa 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 = @""; }

Establezca los títulos en su código donde los está utilizando , porque los cambia muy a menudo durante una ejecución. ("Paso 1" ... "Paso 2", etc.)

-(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]; }]; }

Cambia Huddle para tomar los textos como un argumento si lo deseas.

Siempre quieres self.hud.minShowTime = 0.1; para evitar el parpadeo

Casi siempre self.hud.dimBackground = YES; que también bloquea la interfaz de usuario

Conceptualmente, por supuesto , normalmente tiene que "esperar un poco" para comenzar a trabajar / finalizar el trabajo cuando se inicia un proceso de este tipo, como ocurre con cualquier programación similar con la interfaz de usuario.

Así que en la práctica el código usualmente se verá así ...

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

Handy macro ..

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

Esto es todo el historial ahora :) tutorial!

En mi proyecto, cada uno de los eventos de interacción del usuario realiza una llamada de red (que es TCP, no HTTP). Necesito que el indicador de actividad sea global para mostrar desde un UIViewController aleatorio y se oculte de la clase NetworkActivityManager (una clase personalizada para manejar las actividades de red, que no es una subclase de UIViewController o UIView).

Después de buscar en la web, descubrí que MBProgressHUD se usa para el mismo propósito, pero no pude encontrar un ejemplo de cómo lo usaría globalmente. (Al decir global me refiero a un objeto singleton de MBProgressHUD y métodos de clase para MOSTRAR y OCULTARLO)

Lo siguiente es lo que he intentado todavía, pero, ha fallado: En AppDelegate.h:

@property (nonatomic, retain) MBProgressHUD *hud;

En AppDelegate.m:

@synthesize hud;

En algún objeto aleatorio UIViewController:

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

Y mientras lo oculta, de la clase NetworkActivityManager :

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

Esto hace que el proyecto se bloquee después de un tiempo (debido a problemas de memoria). Estoy usando ARC en mi proyecto y también estoy usando la versión ARC de MBProgressHUD .

¿Me estoy perdiendo de algo?

Pregunta importante:

¿Puedo hacer que MBProgressHUD funcione como UIAlertView? (Decir que me refiero a la implementación de MBProgressHUD independiente de UIView - sa usa showHUDAddedTo: para presentarse) ???

Tenga en cuenta: En el código anterior de ocultación de MBProgressHUD, la vista puede cambiarse de lo que era al mostrar MBProgressHUD.

Cualquier ayuda muy apreciada.


Agregue estos dos métodos para mostrar u ocultar el cargador en su clase de singleton

- (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]; }


Encontré la respuesta de @Matej Bukovinski muy útil, ya que recién comencé a usar Swift y mi propósito al usar sus métodos fue establecer una fuente global para MBProgressHUD, he convertido el código a swift y estoy dispuesto a compartir el siguiente código:

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) }

El código anterior se coloca en un archivo global donde guardo todos mis ayudantes y constantes globales.


Estaba usando el código de @Michael Shang y tenía todo tipo de comportamiento inconsistente al mostrar HUD. Resulta que usar la última ventana no es confiable, ya que el teclado de iOS puede ocultarlo. Entonces, en la mayoría de los casos, debería obtener la ventana utilizando AppDelegate como lo menciona @David Lawson.

Así es como en Swift:

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

Sin embargo, con lo anterior, su HUD aparecerá detrás del teclado de iOS (si se superponen). Si necesita su HUD para superponer el teclado, use el último método de ventana.

En mi caso, lo que estaba sucediendo es que mostraría el HUD y luego llamar a resignFirstResponder() inmediatamente ocultando la ventana a la que se agregó el HUD. Así que esto es algo que hay que tener en cuenta, la única ventana garantizada para quedarse es la primera.

Terminé creando un método que opcionalmente podría agregar el HUD sobre el teclado si fuera necesario:

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 }


Lo he usado de la siguiente manera ... Espero que te ayude ...

en 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; }

Desde vistas aleatorias: -

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


Para mostrar el único MBProgressHUD a la vez, puede verificar si el HUD ya se ha agregado en la misma vista o no. Si no, agregue el HUD de lo contrario no agregue el nuevo 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]; }); }


Usted podría agregar esto a una clase de su gusto:

+ (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]; }

Esto puede ser llamado en cualquier clase. No es necesario mantener una referencia firme al HUD cuando se usan esos métodos de conveniencia de clase.

Dependiendo de su situación específica, probablemente también querrá manejar los casos en que se solicita un nuevo hud antes de que se oculte el otro. Usted podría comer ocultar el hud anterior cuando llega un nuevo o hacer algún tipo de cola, etc.

Ocultar la instancia anterior de HUD antes de mostrar una nueva es bastante sencillo.

+ (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; }


respuesta es la que he estado usando para 5-6 aplicaciones ahora porque también funciona perfectamente dentro de los bloques. Sin embargo he encontrado un problema con él. Puedo hacer que se muestre, pero no puedo hacer que desaparezca si también está presente un UIAlertView. Si miras la implementación puedes ver por qué. Simplemente cambiarlo a esto:

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

Esto asegurará que esté eliminando el HUD de las mismas ventanas en las que se mostró.


Nota : Teniendo en cuenta los puntos de vista que esta pregunta está obteniendo, decidí publicar la forma en que elegí como solución. Esto NO es una respuesta a mi pregunta. (Por lo tanto, la respuesta aceptada sigue siendo aceptada)

En ese momento terminé usando SVProgressHUD ya que era muy simple de integrar y usar.

Todo lo que necesita hacer es arrastrar la carpeta SVProgressHUD / SVProgressHUD a su proyecto. (También puede optar por cocodrilos o cartago)

En Objective-C:

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

En Swift:

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

Además, Mostrar y ocultar HUD debe ejecutarse en el hilo principal . (Específicamente, necesitaría esto para ocultar el HUD en algún cierre en el fondo)

p.ej:

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

Existen métodos adicionales para mostrar mensajes personalizados con HUD, mostrar el éxito / el fracaso durante un corto período de tiempo y el cierre automático.

MBProgressHUD sigue siendo una buena opción para los desarrolladores. Es solo que encontré SVProgressHUD para satisfacer mis necesidades.