Можно ли представить UIAlertView и не продолжать выполнять остальную часть кода в этом методе, пока пользователь не ответит на предупреждение?
Спасибо заранее.
Можно ли представить UIAlertView и не продолжать выполнять остальную часть кода в этом методе, пока пользователь не ответит на предупреждение?
Спасибо заранее.
Я предполагаю, что остановка кода, который вы имели в виду, это остановить устройство для запуска следующего кода, который вы написали после предупреждения.
Для этого просто удалите свой код после вашего предупреждения и поместите этот код в делегат 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
}
}
Не забудьте включить UIAlertViewDelegate в файл .h
Ответ уже принят, но я буду отмечать для всех, кто сталкивается с этим вопросом, что, хотя вы не должны использовать его для нормальной обработки сообщений, в определенных обстоятельствах вам может потребоваться предотвратить продолжение текущего пути выполнения пока появляется предупреждение. Для этого вы можете вращаться в цикле выполнения основного потока.
Я использую этот подход для обработки фатальных ошибок, которые я хочу представить пользователю перед сбоем. В этом случае произошло что-то катастрофическое, поэтому я не хочу возвращаться из метода, вызвавшего ошибку, которая могла бы привести к выполнению другого кода с недопустимым состоянием и, например, с поврежденными данными.
Обратите внимание, что это не предотвратит обработку событий или блокирует запуск других потоков, но поскольку мы представляем предупреждение, которое по сути берет на себя интерфейс, события обычно должны ограничиваться этим предупреждением.
// 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, и попытка найти предыдущий ответ столкнулась с этим открытым вопросом.
Да, это возможно. Следующий пример на С# показывает, как вы можете это сделать с помощью MonoTouch, версия Objective-C должна быть легко написана:
Чтобы сделать это, вы можете просто запустить mainloop вручную. Мне не удалось остановить mainloop напрямую, поэтому вместо этого я запустил mainloop на 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, вы должны прочитать документацию на нем; есть несколько gotchas и некоторый нечетный синтаксис, о котором вы должны знать.
Идет что-то вроде этого:
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];
Это была быстрая реализация, поэтому не стесняйтесь находить какие-либо ошибки; но вы получите эту идею.