Отображение UIAlertViews последовательно - PullRequest
2 голосов
/ 18 мая 2011

У меня есть несколько UIAlertViews, которые я хочу отображать в последовательном порядке, и я могу перейти к отображению следующего UIAlertView только после того, как предыдущий был отклонен (после нажатия пользователем okay).

Я знаю о делегате didDismissWithButtonIndex и добавлении тега, но это не очень помогает, так как может быть вызвано до 3 UIAlertViews, причем необязательно в том же порядке каждый раз. см код:

if(condition 1){
    alert1 = // UIAlertView[[.....
    [alert1 show]
}

if(condition 2){
    alert2 = // UIAlertView[[.....
    [alert2 show]
}

if(condition 3){
    alert3 = // UIAlertView[[.....
    [alert3 show]
}

Выше будет просто добавить 3 оповещения друг над другом (в зависимости от того, сколько условий выполнено), что не то, что я хочу. Я хочу иметь возможность показывать только по одному, а затем следующий (если он есть) после нажатия пользователем кнопки ОК.

У меня была идея, возможно, добавить сообщения в очередь, а затем обработать эту очередь, удаляя оповещение каждый раз, когда оповещение отклоняется, но я не уверен, как это происходит.

Любые идеи будут высоко оценены. Спасибо

Ответы [ 4 ]

0 голосов
/ 24 марта 2013

Вот как я это сделал, используя очередь предупреждений, как вы предложили.

@property (strong, nonatomic) NSMutableArray *alertQueue;
@property (nonatomic) BOOL showingAlert;

- (void)showAlert:(UIAlertView *)alert {
  if (self.showingAlert) {
    [self.alertQueue addObject:alert];
  }
  else {
    self.showingAlert = YES;
    [alert show];
  }
}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
  if ([self.alertQueue count]) {
    UIAlertView *alert = [self.alertQueue objectAtIndex:0];
    [self.alertQueue removeObjectAtIndex:0];
    [alert show];
  }
  else self.showingAlert = NO;
}

Тогда всякий раз, когда вы хотите отобразить предупреждение, вы просто создаете UIAlertView и передаете его в метод showAlert, и он будет отображаться только после того, как все более ранние предупреждения были отклонены.

0 голосов
/ 18 мая 2011

Одна вещь, которую я сделал, это использование блочных UIAlertViews путем добавления категории в AlertView.

Вот файл .h

@interface UIAlertView (WithBlocks)

- (id) initWithTitle:(NSString *)title message:(NSString *)message;
- (void) addButtonWithTitle:(NSString *)title andBlock:(void(^)())block;

@end

Вот файл .m

static NSString *BUTTON_BLOCK_KEY = @"alertview-button-blocks";

@interface UIAlertView()
- (void) runBlock: (void (^)())block;
@end

@implementation UIAlertView (WithBlocks)

/**
 * Initialized an alert view with a title and message.
 */
- (id) initWithTitle:(NSString *)title message:(NSString *)message
{
    self = [self initWithTitle:title message:message delegate:nil cancelButtonTitle:nil otherButtonTitles:nil];
    if (self) {
        self.delegate = self;
        NSMutableArray *buttonBlocks = [NSMutableArray array];
        objc_setAssociatedObject(self, BUTTON_BLOCK_KEY, buttonBlocks, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

    }
    return self;
}

/**
 * Adds a button with a title and a block to be executed when that button is tapped.
 */
- (void) addButtonWithTitle:(NSString *)title andBlock:(void (^)())block
{
    // Add the button
    [self addButtonWithTitle:title];
    NSMutableArray *buttonBlocks = objc_getAssociatedObject(self, BUTTON_BLOCK_KEY);
    if (!block) {
        block = ^{ /* empty block */ };
    }
    [buttonBlocks addObject:[[[block copy] retain] autorelease]];
}

- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
    NSMutableArray *buttonBlocks = objc_getAssociatedObject(self, BUTTON_BLOCK_KEY);
    void (^block)() = (void (^)()) [buttonBlocks objectAtIndex:buttonIndex];

    // Due to a timing issue, the current window is still the UIAlertView for a very
    // short amount of time after it has been dismissed which messes up anything
    // trying to get the current window in the blocks being run.
    // Ergo, the block is being delayed by a tiny bit. (Amount determined through limited testing)
    [self performSelector:@selector(runBlock:) withObject:block afterDelay:0.25];
}

- (void) runBlock: (void (^)())block
{
    block();
}

@end

Затем вы можете вызвать цепочку предупреждений вместе следующим кодом

 void(^continueBlock)(void) = ^{
     // Display more alertviews here
 };

 UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Title" message:@"message"];
 [alert addButtonWithTitle:@"Continue" andBlock:continueBlock];

 [alert addButtonWithTitle:@"Dismiss" andBlock:^{
   // Display more alertviews here
 }
 [alert show];
 [alert release];
0 голосов
/ 13 апреля 2012

Я тоже искал решение этой проблемы.Вот как я решил эту проблему для своего собственного приложения:

static BOOL alertShowing = FALSE;

UIAlertView *alert0 = [[UIAlertView alloc] initWithTitle:@"AlertView 0" message:@"This is the first alert" delegate:self cancelButtonTitle:nil otherButtonTitles:@"Yes",@"No", nil];
[alert0 setTag:0];
alertShowing = TRUE;
[alert0 show];

while (alertShowing) { 
    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.2]];
}

UIAlertView *alert1 = [[UIAlertView alloc] initWithTitle:@"AlertView 1" message:@"This is the second alert" delegate:self cancelButtonTitle:nil otherButtonTitles:@"Yes",@"No", nil];
[alert1 setTag:1];
alertShowing = TRUE;
[alert1 show];

while (alertShowing) { 
    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.2]];
}

// add some more alerts here for dramatic effect ...

Ваш обработчик кнопок должен установить alertShowing = FALSE' на каждом пути выхода.

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
    // Deal with handling responses for your different alerts here.
    switch ([alertView tag]) {
        case 0:
            // handler first alert here
            break;
        case 1:
            // handler second alert here
            break;
        default:
            // etc.
            break;
    }

    alertShowing = FALSE;
}

Возможно, есть лучшие способысидеть и вращаться, чем создавать новый цикл выполнения, и есть некоторый дублирующий код, который, вероятно, можно было бы обобщить лучше.С положительной стороны, это просто и не требует кучу логики очередей.Я использую #define для этого шаблона, чтобы не вводить его вручную, и в моем случае он работал нормально.

0 голосов
/ 18 мая 2011

Вы можете легко сделать это в методе делегата UIAlertView, который вызывается после закрытия представления оповещения. Итак, UIAlertViewDelegate определяет следующий метод делегата:

– alertView:didDismissWithButtonIndex:

Реализуйте этот метод и убедитесь, что ваш класс является делегатом созданных вами UIAlertView. Этот метод является идеальным местом для отображения предупреждения next на основе предупреждения, отклоненного пользователем.

Если ваше требование: «Отображать до трех предупреждений последовательно, но не всегда в одном и том же порядке», я бы, вероятно, поместил предупреждения в массив, а затем в методе делегата получил бы следующее предупреждение из массива. показывать. Это не должно быть более сложным, чем это на самом деле; Ключевым моментом является то, что реализация метода делегата является лучшим местом для показа следующего предупреждения.

Пример псевдокода:

Определить массив; NSMutableArray * alerts _;

- (void)showAlertSequence {
    if ( !alerts_ ) {
        alerts_ = [[NSMutableArray alloc] init];
    }

    [alerts_ addObjects;<My alerts>];

    [self showSequencedAlertFrom:nil];
}

- (BOOL)showSequencedAlertFrom:(UIAlertView *)sourceAlertView {

    if ( !sourceAlertView ) {
        [[alerts_ objectAtIndex:0] show];
    }
    else {
        NSInteger index = [alerts_ indexOfObject:sourceAlertView];

        if ( index < [alerts_ count] ) {
            [[alerts_ objectAtIndex:index++] show];
        }
    }

    return NO;
}

– alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)index {

    // Show the next alert or clean up if we're at the end of the sequence.
    if ( ![self showSequencedAlertFrom:alertView] ) {
        [alerts_ removeAllObjects];
    }
}   

в сторону; три последовательных оповещения действительно будут раздражать вас пользователей;)

...