按顺序显示UIAlertViews

时间:2011-05-18 13:43:29

标签: objective-c uiview uialertview alert

我想要按顺序显示几个UIAlertViews,只有在前一个UIAlertView被解除后才会显示下一个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个警报(取决于满足的条件数量),这不是我想要的。我希望能够在用户点击确定按钮后一次只显示一个,然后显示下一个(如果有)。

我想到可能会将消息添加到队列中,然后处理该队列,每次取消警报时都会删除警报,但我不确定id是如何进行的。

任何想法都会非常感激。 感谢

4 个答案:

答案 0 :(得分:0)

您可以在UIAlertView委托方法中轻松完成此操作,一旦取消警报视图,就会调用此方法。因此,UIAlertViewDelegate定义了以下委托方法:

– alertView:didDismissWithButtonIndex:

实现该方法,并确保您的类是您创建的UIAlertViews的委托。此方法是根据用户解散的下一个警告显示的理想场所。

如果您的要求是“按顺序显示最多三个警报,但并不总是以相同的顺序显示”我可能会将警报放入数组中,然后在委托方法中获取数组中的下一个警报显示。它不一定比那更复杂;关键是委托方法实现是显示下一个警报的最佳位置。

伪代码示例:

定义一个数组; NSMutableArray *警告_;

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

撇开;三个连续警报将真正惹恼用户;)

答案 1 :(得分:0)

我做过的一件事就是使用基于块的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];

答案 2 :(得分:0)

我也在寻找这个问题的解决方案。这是我最终为自己的应用程序解决它的方式:

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来防止手动输入它,并且它在我的情况下运行良好。

答案 3 :(得分:0)

以下是我使用像你建议的那样使用警报队列的方法。

@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方法,它只会在所有早期警报被解除后显示。