Controllare se un UIAlertView sta mostrando
-
22-09-2019 - |
Domanda
Ho un metodo che i messaggi HTTP i dati e visualizza un UIAlertView se si verifica un errore. Se ho più post HTTP vi mostrerò UIAlertView multiplo per ogni errore.
Voglio mostrare un UIAlertView solo se non sta mostrando altri UIAlertView. Come è possibile determinare questo?
Soluzione
sull'oggetto che chiamate impostato un Ivar prima di invocare il metodo show sul UIAlertView.
...
if (!self.alertShowing) {
theAlert = [[UIAlertView alloc] initWithTitle:title message:details delegate:self cancelButtonTitle:nil otherButtonTitles:@"Okay", nil];
self.alertShowing = YES;
[theAlert show];
}
...
Poi, nel tuo metodo delegato per l'avviso gestire impostando la tua bandiera Ivar a nessuno:
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
...
self.alertShowing = NO;
}
Se si desidera che le segnalazioni per mostrare in sequenza, vorrei inviare notifiche per aggiungere ogni messaggio a una coda e poi prendere solo un messaggio dalla coda dopo un allarme è respinto.
Altri suggerimenti
Perché non solo controllare la proprietà visibile, gestito dalla classe 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];
}
Se è possibile controllare le altre viste di avviso, controllare la proprietà visible
per ciascuno di essi.
In iOS 6 o prima, quando viene visualizzato un avviso, sarà spostato in una _UIAlertOverlayWindow. Pertanto, un metodo piuttosto fragile è quello di scorrere tutte le finestre e verificare se ci sono subviews 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;
Questo è documentato poiché dipende dalla gerarchia vista interna, anche se Apple non può lamentarsi di questo. Un metodo più affidabile, ma anche più documentato è quello di verificare se [_UIAlertManager visibleAlert]
è pari a zero .
Questi metodi non possono controllare se viene mostrato un UIAlertView da SpringBoard.
- (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;
}
Un'altra opzione che funziona attraverso l'intera applicazione e non coinvolge camminare lo stack vista è quello di creare una sottoclasse UIAlertView
a MyUIAlertView
, aggiungere una statica (classe) BOOL alertIsShowing
variabile, e ignorare il selettore -(void)show
.
Nel vostro selettore show
override, controllare la variabile alertIsShowing
. Se è YES
quindi riprovare dopo un ritardo (uso dispatch_after
o impostare un NSTimer
). Se si tratta di NO
, andare avanti e chiamare [super show]
e assegnare YES
a alertIsShowing
; quando la vista avviso è nascosto, impostare alertIsShowing
torna a NO
(avrete bisogno di essere intelligente sulla gestione del delegato).
Infine, passare attraverso e sostituire tutte le istanze UIAlertView
con MyUIAlertView
.
Credo che funzionerà:
-(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
}
Swift:
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;
}
Alcune note sulla mia ricerca per trovare l'UIAlertView nella gerarchia della vista:
Ho provato a ciclo attraverso tutte le [UIApplication sharedApplication].windows
vista del modo ricorsivo, ma non ho trovato nulla.
La proprietà windows
di documenti UIApplication
afferma quanto segue:
Questa proprietà contiene gli oggetti UIWindow attualmente associati l'applicazione. La lista non include le finestre create e gestite dal Sistema , ad esempio la finestra utilizzata per visualizzare la barra di stato.
Quindi questo mi ha fatto capire che la UIWindow
in cui potrebbe essere situato UIAlertView
non è nemmeno presentato a noi.
Tuttavia, v'è anche una proprietà su UIApplication
chiamato keyWindow
. Su scorrendo che, ho scoperto lezioni private che comporre una visione avviso:
In iOS 7:. _UIModalItemHostingWindow
, _UIModalItemAlertContentView
, _UIBackdropEffectView
etc
Su iOS 8:. _UIAlertControllerActionView
, _UIAlertControllerShadowedScrollView
, _UIBackdropView
etc
non riuscivo a trovare il UIAlertView
che ho presentato, ma piuttosto, un gruppo di classi che la compongono internamente. Quindi, per rispondere alla domanda iniziale , probabilmente si può utilizzare la proprietà keyWindow
e vedere se notate queste classi, ma la vostra applicazione potrebbe ottenere respinto per cercare di verificare la presenza di lezioni private.
Per la gente che utilizzano, il più recente, UIAlertController
disponibile per iOS 8 potrebbe ottenere il riferimento ad essa tramite:
[UIApplication sharedApplication].keyWindow.rootViewController.presentedViewController
.