Pregunta

Tengo un método que publica datos HTTP y muestra una vista de UialertView si hay un error. Si tengo múltiples publicaciones HTTP, mostraré múltiples uialertView para cada error.

Quiero mostrar un UialertView solo si no muestra otro UialertView. ¿Cómo puedo determinar esto?

¿Fue útil?

Solución

En el objeto que las llamadas establecen un IVAR antes de invocar el método de programa en su UialertView.

...

if (!self.alertShowing) {
    theAlert = [[UIAlertView alloc] initWithTitle:title message:details delegate:self cancelButtonTitle:nil otherButtonTitles:@"Okay", nil];
    self.alertShowing = YES;
    [theAlert show];
}

...

Luego, en su método delegado para la alerta, administre su bandera ivar en no:

- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
  ...
      self.alertShowing = NO;
}

Si desea que las alertas se muestren secuencialmente, publicaría notificaciones para agregar cada mensaje a una cola y luego solo quitaría un mensaje a la cola después de que se descarta una alerta.

Otros consejos

¿Por qué no simplemente consultar la propiedad visible, mantenida por la clase UialertView?

if (_alert) //alert is a retained property
{
    self.alert = [[[UIAlertView alloc] initWithTitle:@"Your Title"
                                             message:@"Your message" 
                                            delegate:self
                                   cancelButtonTitle:@"Cancel"
                                   otherButtonTitles:@"OK"] autorelease];
}
if (!_alert.visible)
{
    [_alert show];
}

Si puede controlar las otras vistas de alerta, verifique el visible propiedad para cada uno de ellos.


En iOS 6 o antes, cuando aparezca una alerta, se trasladará a un _uialerToverLayWindow. Por lo tanto, un método bastante frágil es iterar a través de todas las ventanas y verificar si hay alguna subvisión de UialertView.

for (UIWindow* window in [UIApplication sharedApplication].windows) {
  NSArray* subviews = window.subviews;
  if ([subviews count] > 0)
    if ([[subviews objectAtIndex:0] isKindOfClass:[UIAlertView class]])
      return YES;
}
return NO;

Esto es indocumentado, ya que depende de la jerarquía de visión interna, aunque Apple no puede quejarse de esto. Un método más confiable pero aún más indocumentado es verificar si [_UIAlertManager visibleAlert] es nulo.

Estos métodos no pueden verificar si se muestra un UialertView desde el trampolín.

- (BOOL)checkAlertExist {
    for (UIWindow* window in [UIApplication sharedApplication].windows) {
        NSArray* subviews = window.subviews;
        if ([subviews count] > 0) {
            for (id cc in subviews) {
                if ([cc isKindOfClass:[UIAlertView class]]) {
                    return YES;
                }
            }
        }
    }
    return NO;
}

Otra opción que funciona en toda la aplicación y no implica caminar por la pila View es subclase UIAlertView a MyUIAlertView, agregue una variable estática (clase) BOOL alertIsShowing, y anular el -(void)show selector.

En tu anulación show Selector, consulte el alertIsShowing variable. Si es YES Luego intente nuevamente después de un retraso (use dispatch_after o establecer un NSTimer). Si es NO, adelante y llame [super show] y asignar YES a alertIsShowing; Cuando la vista de alerta esté oculta, establezca alertIsShowing de regreso NO (Tendrá que ser inteligente para manejar el delegado).

Finalmente, pase y reemplace todo UIAlertView instancias con MyUIAlertView.

Creo que funcionará:

-(BOOL) doesAlertViewExist {
    if ([[UIApplication sharedApplication].keyWindow isMemberOfClass:[UIWindow class]])
    {
        return NO;//AlertView does not exist on current window
    }
    return YES;//AlertView exist on current window
}

Rápido:

func showAlert(withTitle title: String, message: String, viewController: UIViewController) {
    if viewController.presentedViewController == nil { // Prevent multiple alerts at the same time
        let localizedTitle = NSLocalizedString(title, comment: "")
        let localizedMessage = NSLocalizedString(message, comment: "")
        let alert = UIAlertController(title: localizedTitle, message: localizedMessage, preferredStyle: .Alert)
        let action = UIAlertAction(title: "OK", style: .Default, handler: nil)
        alert.addAction(action)

        viewController.presentViewController(alert, animated: true, completion: nil)
    }
}
// initialize default flag for alert... If alert is not open set isOpenAlert as NO
BOOL isAlertOpen;
isAlertOpen = NO;
if (isAlertOpen == NO) {
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Alert" message:@"Alert is Open" delegate:self cancelButtonTitle:@"Okay!!" otherButtonTitles: nil];
    [alert show];
    // Now set isAlertOpen to YES
    isAlertOpen = YES;
}
else
{
    //Do something
}
+ (BOOL)checkAlertExist {

    for (UIWindow* window in [UIApplication sharedApplication].windows) {
        if ([window.rootViewController.presentedViewController isKindOfClass:[UIAlertController class]]) {
            return YES;
        }
    }
    return NO;
}

Algunas notas sobre mi búsqueda para encontrar el UialertView en la jerarquía de vista:

Traté de recorrer todo el [UIApplication sharedApplication].windows View es recursivamente pero no pudo encontrar nada.

los windows propiedad de UIApplication Docs establece lo siguiente:

Esta propiedad contiene los objetos UIWindow actualmente asociados con la aplicación. Esta lista no incluye Windows creadas y administradas por el sistema., como la ventana utilizada para mostrar la barra de estado.

Entonces esto me hizo darme cuenta de que el UIWindow dónde UIAlertView Se podría ubicar ni siquiera se nos presenta.

Sin embargo, también hay una propiedad en UIApplication llamó keyWindow. Al recorrer eso, encontré clases privadas que componían una vista de alerta:

En iOS 7: _UIModalItemHostingWindow, _UIModalItemAlertContentView, _UIBackdropEffectView etc.

En iOS 8: _UIAlertControllerActionView, _UIAlertControllerShadowedScrollView, _UIBackdropView etc.

No pude encontrar el UIAlertView que presenté, pero más bien, un montón de clases que lo componen internamente. Entonces, para responder a la pregunta original, probablemente puedas usar el keyWindow propiedad y ver si nota estas clases, pero su aplicación podría ser rechazada por tratar de verificar las clases privadas.

Para la gente que usa, el más nuevo, UIAlertController Disponible para iOS 8 podría obtener la referencia usando:[UIApplication sharedApplication].keyWindow.rootViewController.presentedViewController.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top