顺序显示 UIAlertView

发布于 2024-11-08 20:22:20 字数 601 浏览 3 评论 0 原文

我有几个 UIAlertView,我想按顺序显示,并且只有在前一个 UIAlertView 被关闭(用户单击“确定”)后才继续显示下一个 UIAlertView。

我了解 didDismissWithButtonIndex 委托并添加标签,但这并没有太大帮助,因为最多可能会调用 3 个 UIAlertView,而且不一定每次都以相同的顺序调用。查看代码:

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

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

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

上面只会添加 3 个警报(取决于满足多少条件),这不是我想要的。我希望能够一次只显示一个,然后在用户单击“确定”按钮后显示下一个(如果有)。

我的想法是将消息添加到队列中,然后处理该队列,每次解除警报时删除警报,但我不确定 id 是如何做到这一点的。

任何想法将不胜感激。 谢谢

I have several UIAlertViews that i want to display in a sequential order, and only move on to display the next UIAlertView once the previous one has been dismissed (by user clicking okay).

I know about the didDismissWithButtonIndex delegate and adding a tag, but this doesn't really help too much as there could be upto 3 UIAlertViews invoked and not necessarily in the same order everytime. see code:

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

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

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

The above will just add 3 Alerts on top of each other (depending on how many conditions are met) which is not what I want. I want to be able to only show one at a time and then the next one (if there is one) after the user hits the ok button.

I had the idea of maybe adding the messages to a queue and then processing that queue removing the alert every time an alert is dismissed but i'm not sure how id go about doing that.

Any ideas would be much appreciated.
Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

明月夜 2024-11-15 20:22:20

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

– alertView:didDismissWithButtonIndex:

实现该方法,并确保您的类是您创建的 UIAlertView 的委托。此方法是根据用户取消的警报显示下一个警报的完美位置。

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

伪代码示例:

定义一个数组; 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];
    }
}   

顺便说一句;三个连续的警报真的会惹恼您的用户;)

You could easily do it in the UIAlertView delegate method, called once an alert view is dismissed. So, UIAlertViewDelegate defines the following delegate method:

– alertView:didDismissWithButtonIndex:

Implement that method, and make sure your class is the delegate of the UIAlertViews you create. This method is the perfect place to then show the next alert based on the one being dismissed by the user.

If your requirement is "Display up to three alerts, sequentially, but not always in the same order" i'd probably put the alerts in to an array, and then in the delegate method get the next alert out of the array to show. It doesn't have to be any more complex than that really; the key thing is that the delegate method implementation is the best place to show the next alert.

Pseudo Code Example:

Define an array; 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];
    }
}   

As an aside; three sequential alerts will really annoy you users ;)

阳光①夏 2024-11-15 20:22:20

我所做的一件事是通过在 AlertView 上添加一个类别来使用基于块的 UIAlertViews。

这是 .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];

One thing that I've done is used block based UIAlertViews by adding a category on AlertView.

Here is the .h file

@interface UIAlertView (WithBlocks)

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

@end

Here is the .m file

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

Then you can call chain the alertviews together by the following code

 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];
一指流沙 2024-11-15 20:22:20

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

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,以避免手动输入它,并且它在我的情况下工作得很好。

I was looking for a solution to this problem as well. Here's the way I ended up solving it for my own app:

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 ...

Your button handler must set alertShowing = FALSE' in every exit path.

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

There may be better ways to sit and spin than creating a new run loop, and there's some duplicate code that probably could be genericized better. On the plus side, it's straightforward and doesn't require a bunch of queuing logic. I'm using a #define for this pattern to keep from having to hand-type it, and it has worked fine in my case.

寄与心 2024-11-15 20:22:20

这就是我如何使用您建议的警报队列来完成此操作。

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

Here's how I did it using a queue of alert's like you suggested.

@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;
}

Then whenever you want to display an alert, you just create the UIAlertView and pass it to the showAlert method and it will only show up after all earlier alerts have been dismissed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文