Использование UIAlertView в манере, аналогичной Windows MessageBox ()? - PullRequest
4 голосов
/ 02 мая 2009

Я новичок в iPhone и хотел бы иметь возможность использовать UIAlertView аналогично Windows MessageBox() или MessageDlg() в Delphi.

Например, у меня есть метод, который должен запрашивать у пользователя подтверждение чего-либо и действовать на основе его ответа.

например. (Псевдокод):

-(void)doSomething
{
  [doStep1];
  [doStep2];
  var myValue = [getDefaultValue];

  if (myValue = nil)
  {
    if [promptUser(@"No value in setting. Use the default value?")] //UIAlertView here?
    {
       myValue = @"defaultValue";
    }
    else
      return;  // bug out of the routine 'cause we have no value.
  }

  [doStep3 withValue:myValue];

}

Или, другими словами, есть ли способ использовать UIAlertView, чтобы задать пользователю вопрос в рамках подпрограммы как способ управления логическим потоком этой подпрограммы?

Ответы [ 6 ]

5 голосов
/ 03 мая 2009

Нет никаких причин для создания подкласса UIAlertView вообще. Для этого и нужны делегаты. Все, что вам нужно, это класс (например, ваш контроллер представления), поддерживающий протокол UIAlertViewDelegate, и установить свойство делегата UIAlertView для этого класса. Затем вы реализуете alertView: clickedButtonAtIndex: метод в этом классе и alertViewCancel: метод, если вы хотите специально обрабатывать отмены по-другому.

Подробнее об этом можно прочитать в документации UIAlertView и в документации UIAlertViewDelegate .

4 голосов
/ 02 мая 2009

Я понятия не имею, что такое MessageDlg(), но вы, безусловно, можете подкласс UIAlertView и обрабатывать ответ диалога, основанный на том, какая кнопка нажата, например:

Настройка заголовка подкласса UIAlertView:

//
//  ARReachabilityAlertView.h
//

#import <UIKit/UIKit.h>

@interface ARReachabilityAlertView : UIAlertView <UIAlertViewDelegate> {
}

@end

Настройка реализации подкласса UIAlertView:

//
//  ARReachabilityAlertView.m
//

#import "ARReachabilityAlertView.h"

@implementation ARReachabilityAlertView

- (id)initWithFrame:(CGRect)frame {
  if (self = [super initWithFrame:frame]) {
    [self setTitle:@"Error"];
    [self setMessage:@"This application won't run without a network connection. Do you want to quit?"];
    [self addButtonWithTitle:@"Quit"];
    [self addButtonWithTitle:@"Continue"];
    [self setDelegate:self];
  }
  return self;
}

- (void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
  if (buttonIndex == 0)
    exit(0); // quit application if "Quit" is pressed; otherwise, do nothing
}

- (void) drawRect:(CGRect)rect {
  [super drawRect:rect];
}

- (void) dealloc {
  [super dealloc];
}

@end

Обратите внимание на метод делегата alertView:clickedButtonAtIndex:. Это обрабатывает условия, которые вы используете, чтобы решить, как будет работать приложение. Вы можете отправить NSNotification отсюда или вызвать метод в делегате приложения, как хотите.

В моем примере это UIAlertView создается, если нет сетевого подключения, и приложение закрывается, если пользователь нажимает «Выход» в представлении предупреждений. В противном случае, если пользователь нажимает «Продолжить», приложение продолжает работать как обычно.

Обратите внимание, что реализация подкласса требует вызова метода drawRect:. Я не уверен, является ли это ошибкой или нет, так как я ожидал, что метод drawRect: будет вызван в суперклассе; Я подал в Apple отчет об ошибке, но ничего не слышал. Прокомментируйте это, если хотите увидеть, каким будет эффект - это довольно интересно.

2 голосов
/ 01 октября 2012

Благодаря @ miguel.de.icaza я нашел свое решение, как показано ниже ( часть кода ):

@interface MyClass: NSObject <UIAlertViewDelegate>
{
   int confirmed;
}
- (BOOL) removeObjectAtIndex:(NSUInteger)index;
@end

@implementation

- (BOOL) removeObjectAtIndex:(NSUInteger)index
{   
    // delete confirmation alert
    confirmed = -1;

    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Delete confirmation" message:@"Are you sure to delete object" delegate:self cancelButtonTitle:@"Yes" otherButtonTitles: @"No", nil];
    alert.tag = 2;
    [alert show];
    [alert release];

    // wait for confirm (0 or 1)
    while (confirmed == -1) {
        // this is what you need!!!
        [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.5]];
    }

    if (confirmed) {
        [myObjects removeObjectAtIndex:index];
        return YES;
    }
    else
        return NO;
}

- (void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    switch (alertView.tag) {
        case 1:
            // ...
            break;
        case 2:
            if (buttonIndex == 0) // delete confirmed
                confirmed = 1;
            else                  // dismiss
                confirmed = 0;
            break;
        default:
            break;
    }
}

@end
2 голосов
/ 13 февраля 2011

Просто быстрый совет: если вы хотите, чтобы класс был делегатом для нескольких UIAlertView, просто используйте свойство tag, чтобы сказать, кто есть кто:

UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Clear all" message:@"Are you sure you want to erase everything?" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK", nil];
alert.tag = ALERT_DELETE_TAG;
[alert autorelease];
[alert show];

Методы делегатов вызываются с UIAlertView в качестве первого аргумента, и вы можете проверить, кто там является инициатором.

2 голосов
/ 26 января 2011

Для этого вы можете запустить основной цикл вручную. Мне не удалось остановить основной цикл напрямую, поэтому я вместо этого запускаю основной цикл в течение 0,5 секунды и жду, пока пользователь ответит.

Я столкнулся с этим вопросом при исследовании проблемы для пользователя C # / MonoTouch на iPhone. Пример ниже написан для MonoTouch / C #, но должен быть тривиальным для перевода в Objective-C

Следующая функция показывает, как можно реализовать модальный запрос с помощью вышеуказанного подхода:

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;
}
2 голосов
/ 02 мая 2009

Я полагаю, что вы хотите использовать UIAlertView в качестве модального окна оповещения (в том смысле, что вы хотите, чтобы ваш код прекращал работать, пока пользователь не сделает выбор). Нет простого способа сделать это, и очень рекомендуется, чтобы вы НЕ кодировали iPhone таким образом. Я думаю, что объяснение Алекса - хорошее решение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...