【问题标题】:iphone UIAlertView Modaliphone UIAlertView 模态
【发布时间】:2011-05-13 23:47:32
【问题描述】:

是否可以呈现一个 UIAlertView 并且在用户响应警报之前不继续执行该方法中的其余代码?

提前致谢。

【问题讨论】:

  • 不停止代码是否意味着它无法响应用户按下按钮?

标签: iphone objective-c modal-dialog uialertview


【解决方案1】:

我猜停止你的意思是停止设备运行你在警报视图之后编写的下一个代码

为此,只需在您的 alertview 之后删除您的代码并将该代码放入 alertview 委托

-(void) yourFunction
{
     //Some code
     UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:@"Your Message" delegate:self cancelButtonTitle:nil otherButtonTitles:@"OK", nil];
            [alert show];
            [alert release];
     //Remove all your code from here put it in the delegate of alertview
}
-(void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:    (NSInteger)buttonIndex 
{
if(buttonIndex==0)
    {
        //Code that will run after you press ok button 
    }
}

不要忘记在 .h 文件中包含 UIAlertViewDelegate

【讨论】:

  • 呃。有点伤心,这是处理这个问题的最好方法。 “糟糕,我刚刚意识到我应该在执行代码之前确保用户想要这样做。现在让我重新组织我的所有代码......”
  • 悲伤,但更异步。
  • 如果我有 'yourFunction' 的参数怎么办?我怎样才能把它带到代表那里?
  • 您可以尝试使用块而不是委托的警报视图。见github.com/ryanmaxwell/UIAlertView-Blocks
【解决方案2】:

答案已被接受,但我会提醒遇到此问题的任何人,虽然您不应该将其用于正常的警报处理,但在某些情况下,您可能希望阻止当前的执行路径继续在呈现警报时。为此,您可以在主线程的运行循环中旋转。

我使用这种方法来处理我想在崩溃之前呈现给用户的致命错误。在这种情况下,发生了一些灾难性的事情,所以我不想从导致错误的方法返回,这可能允许其他代码以无效状态执行,例如损坏数据。

请注意,这不会阻止事件被处理或阻止其他线程运行,但由于我们呈现一个实质上接管接口的警报,因此事件通常应仅限于该警报。

// Present a message to the user and crash
-(void)crashNicely {

  // create an alert
  UIAlertView *alert = ...;

  // become the alert delegate
  alert.delegate = self;

  // display your alert first
  [alert show];

  // spin in the run loop forever, your alert delegate will still be invoked
  while(TRUE) [[NSRunLoop currentRunLoop] runUntilDate:[NSDate distantFuture]];

  // this line will never be reached
  NSLog(@"Don't run me, and don't return.");

}

// Alert view delegate
- (void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex {
  abort(); // crash here
}

【讨论】:

  • 谢谢。我不知道为什么接受其他答案,但只有您的解决方案有效。
【解决方案3】:

不,但简单的解决方法是在您呈现 UIAlertView 时拆分您的代码 - 并在解除警报时从您的委托方法开始第二部分。

【讨论】:

    【解决方案4】:

    我刚刚遇到了这个关于 MonoTouch 的问题,试图找到以前的答案时遇到了这个悬而未决的问题。

    是的,这是可能的。下面的 C# 示例展示了如何使用 MonoTouch 来实现,它的 Objective-C 版本应该很容易编写:

    为此,您可以手动运行主循环。我没有设法直接停止主循环,所以我改为运行主循环 0.5 秒并等待用户响应。

    以下函数显示了如何使用上述方法实现模态查询:

    int WaitForClick ()
    {
        int clicked = -1;
        var x = new UIAlertView ("Title", "Message",  null, "Cancel", "OK", "Perhaps");
        x.Show ();
        bool done = false;
        x.Clicked += (sender, buttonArgs) => {
            Console.WriteLine ("User clicked on {0}", buttonArgs.ButtonIndex);
        clicked = buttonArgs.ButtonIndex;
        };    
        while (clicked == -1){
            NSRunLoop.Current.RunUntil (NSDate.FromTimeIntervalSinceNow (0.5));
            Console.WriteLine ("Waiting for another 0.5 seconds");
        }
    
        Console.WriteLine ("The user clicked {0}", clicked);
        return clicked;
    }
    

    【讨论】:

    • @Krumelur:你能发布你正在使用的代码吗?我对 C# 不熟悉,对 Objective-C 也几乎不熟悉,所以我无法将其转换为我可以使用的东西。
    • @GeneralMike 我正在使用 Miguel 上面发布的代码。
    • 此技术在 iOS7 中不再适用,因为一旦启动 RunLoop,UIAlertView 委托将永远不会被调用。详情请见:stackoverflow.com/questions/18607349/…
    【解决方案5】:

    如果需要等待的代码都在同一个方法中(或可以),块可以是另一种选择。我创建了一个 UIAlertView 子类来处理这个问题。请记住,执行仍然会在 [alert show] 调用之后继续执行;这只是为您提供了一种传递堆栈变量的方法,而无需创建新的中间类变量。另外,如果你还不熟悉 Objective-C 块,你应该阅读它的文档;您应该注意一些问题和一些奇怪的语法。

    是这样的:

    typedef void (^MyAlertResult)(NSInteger clickedButtonIndex);
    
    @interface MyBlockAlert : UIAlertView
    {
        MyAlertResult finishedBlock;
    }
    - (void) showWithCompletionBlock:(MyAlertResult)block;
    ...
    
    - (void) showWithCompletionBlock:(MyAlertResult)block
    {
        self.delegate = self;
        finishedBlock = [block copy];
        [self show];
    }
    
    - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
    {
        finishedBlock(buttonIndex);
        [finishedBlock release];
        finishedBlock = nil;
    }
    

    这样使用:

    __block NSArray* arrayOfDeletes; // set to something
    MyBlockAlert* areYouSureAlert = [[MyBlockAlert alloc] initWithTitle:@"Really delete?" message:@"Message" delegate:nil cancelButtonTitle:@"Cancel" otherButtonTitles:@"Delete", nil];
    
    [arrayOfDeletes retain]; // Make sure retain count is +1
    
    [areYouSureAlert showWithCompletionBlock:
    ^(NSInteger clickedButtonIndex)
    {
        if (clickedButtonIndex == 1)
        {
            // Clicked okay, perform delete
        }
        [arrayOfDeletes release];
    }];
    [areYouSureAlert release];
    

    这是一个快速实现,因此请随时查找任何错误;但你明白了。

    【讨论】:

    • 沿着这些思路(使用块)的东西更干净,不需要到处都有代表。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多