【发布时间】:2011-05-13 23:47:32
【问题描述】:
是否可以呈现一个 UIAlertView 并且在用户响应警报之前不继续执行该方法中的其余代码?
提前致谢。
【问题讨论】:
-
不停止代码是否意味着它无法响应用户按下按钮?
标签: iphone objective-c modal-dialog uialertview
是否可以呈现一个 UIAlertView 并且在用户响应警报之前不继续执行该方法中的其余代码?
提前致谢。
【问题讨论】:
标签: iphone objective-c modal-dialog uialertview
我猜停止你的意思是停止设备运行你在警报视图之后编写的下一个代码
为此,只需在您的 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
【讨论】:
答案已被接受,但我会提醒遇到此问题的任何人,虽然您不应该将其用于正常的警报处理,但在某些情况下,您可能希望阻止当前的执行路径继续在呈现警报时。为此,您可以在主线程的运行循环中旋转。
我使用这种方法来处理我想在崩溃之前呈现给用户的致命错误。在这种情况下,发生了一些灾难性的事情,所以我不想从导致错误的方法返回,这可能允许其他代码以无效状态执行,例如损坏数据。
请注意,这不会阻止事件被处理或阻止其他线程运行,但由于我们呈现一个实质上接管接口的警报,因此事件通常应仅限于该警报。
// 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
}
【讨论】:
不,但简单的解决方法是在您呈现 UIAlertView 时拆分您的代码 - 并在解除警报时从您的委托方法开始第二部分。
【讨论】:
我刚刚遇到了这个关于 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;
}
【讨论】:
如果需要等待的代码都在同一个方法中(或可以),块可以是另一种选择。我创建了一个 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];
这是一个快速实现,因此请随时查找任何错误;但你明白了。
【讨论】: