У меня есть метод, который отправляет данные HTTP и отображает UIAlertView, если есть ошибка. Если у меня есть несколько сообщений HTTP, я буду показывать несколько UIAlertView для каждой ошибки.
Я хочу показать UIAlertView, только если не показывает другой UIAlertView. Как я могу это определить?
Ответ 1
На объекте, который вызывает набор ivar перед вызовом метода show в вашем UIAlertView.
...
if (!self.alertShowing) {
theAlert = [[UIAlertView alloc] initWithTitle:title message:details delegate:self cancelButtonTitle:nil otherButtonTitles:@"Okay", nil];
self.alertShowing = YES;
[theAlert show];
}
...
Затем в вашем методе делегирования для предупреждения управляйте установкой флага ivar на no:
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
...
self.alertShowing = NO;
}
Если вы хотите, чтобы предупреждения отображались последовательно, я отправлял уведомления, чтобы добавить каждое сообщение в очередь, а затем только вывести сообщение из очереди после отклонения предупреждения.
Ответ 2
Почему бы просто не проверить свойство visible, поддерживаемое классом 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];
}
Ответ 3
Если вы можете контролировать другие виды предупреждений, проверьте visible
свойство для каждого из них.
В iOS 6 или раньше, когда появляется предупреждение, оно будет перемещено в окно _UIAlertOverlayWindow. Поэтому довольно хрупкий метод состоит в том, чтобы перебрать все окна и проверить, есть ли какие-либо подпредставления 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;
Это недокументировано, поскольку зависит от внутренней иерархии представлений, хотя Apple не может пожаловаться на это. Более надежный, но еще более недокументированный метод - проверить, [_UIAlertManager visibleAlert]
ли [_UIAlertManager visibleAlert]
nil.
Эти методы не могут проверить, отображается ли UIAlertView из SpringBoard.
Ответ 4
- (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;
}
Ответ 5
Другая опция, которая работает во всем приложении и не включает в себя хостинг стека представления, заключается в подклассе UIAlertView
- MyUIAlertView
, добавляет статическую (класс) переменную BOOL alertIsShowing
и переопределяет селектор -(void)show
.
В вашем переопределенном селекторе show
проверьте переменную alertIsShowing
. Если он YES
, повторите попытку после задержки (используйте dispatch_after
или установите NSTimer
). Если он NO
, продолжайте и вызовите [super show]
и присвойте YES
alertIsShowing
; когда вид предупреждения скрыт, установите alertIsShowing
обратно на NO
(вам нужно быть умным в обработке делегата).
Наконец, просмотрите и замените все экземпляры UIAlertView
на MyUIAlertView
.
Ответ 6
Я думаю, что это сработает:
-(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
}
Ответ 7
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)
}
}
Ответ 8
// 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
}
Ответ 9
Некоторые заметки о моем поиске для поиска UIAlertView в иерархии представлений:
Я попытался просмотреть рекурсивно все представления [UIApplication sharedApplication].windows
, но ничего не смог найти.
Свойство windows
UIApplication
docs утверждает следующее:
Это свойство содержит объекты UIWindow, которые в настоящее время связаны с приложение. Этот список не включает окна, созданные и управляемые system, например, окно, отображаемое в строке состояния.
Итак, это заставило меня понять, что UIWindow
, где UIAlertView
может быть найдено, даже не представляется нам.
ОДНАКО, на UIApplication
есть свойство keyWindow
. После этого я обнаружил частные классы, которые будут составлять представление предупреждения:
В iOS 7: _UIModalItemHostingWindow
, _UIModalItemAlertContentView
, _UIBackdropEffectView
и т.д.
В iOS 8: _UIAlertControllerActionView
, _UIAlertControllerShadowedScrollView
, _UIBackdropView
и т.д.
Я не мог найти UIAlertView
, который я представил, а скорее кучу классов, которые составляют его внутренне. Чтобы ответить на исходный вопрос, вы, вероятно, можете использовать свойство keyWindow
и посмотреть, заметили ли вы эти классы, но ваше приложение может быть отклонено для проверки на наличие частных классов.
Для людей, использующих новый, UIAlertController
, доступный для iOS 8, можно получить ссылку на него, используя:
[UIApplication sharedApplication].keyWindow.rootViewController.presentedViewController
.
Ответ 10
+ (BOOL)checkAlertExist {
for (UIWindow* window in [UIApplication sharedApplication].windows) {
if ([window.rootViewController.presentedViewController isKindOfClass:[UIAlertController class]]) {
return YES;
}
}
return NO;
}