【问题标题】:Validations for custom alert view自定义警报视图的验证
【发布时间】:2014-04-16 12:58:20
【问题描述】:

我已将自定义视图添加到警报视图。

MyViewController *myViewController = [self.storyboard instantiateViewControllerWithIdentifier: @"MyView"];
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil message:nil delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"Submit", nil];                                                                                                           
[alertView setValue: myViewController.view  forKey:@"accessoryView"];              
[alertView show];

myViewController.view 中有一些文本字段。警报视图有两个按钮“提交”和“取消”。

点击“提交”按钮时,我需要验证文本字段中的输入。如果输入无效,我不想关闭警报。例如。如果电子邮件无效,我将显示另一个警报,提示“电子邮件无效”。我将如何实现这一目标?到目前为止,我尝试了以下事情:

1) 用以下方法编写验证逻辑:

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex;

但执行此方法后警报视图消失。

2) 继承 UIAlertView。我试图在子类 UIAlertView 中覆盖以下方法:

- (void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animated

虽然我点击警报视图上的任何按钮,但不会调用此方法。苹果说,

The UIAlertView class is intended to be used as-is and does not support subclassing. The view hierarchy for this class is private and must not be modified.

我今天花了很多时间来解决这个问题,但没有运气..!!请帮我。

【问题讨论】:

  • 只需创建自己的 AlertView,因为 alertview 只能按原样使用。您正在使用私有方法来设置您的自定义视图,这可能会导致您的应用被拒绝。
  • 感谢您的建议@rckoenes..!!
  • 我认为你可以使用委托方法之外的东西。 - (void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex;
  • 或者您可以将“提交”UIButton 放在 myViewController 中,它看起来类似于具有相同尺寸的取消按钮,位于 myViewController.view 的底部,并在 alertView 中只保留一个按钮来取消警报。

标签: ios objective-c ios7 uiviewcontroller uialertview


【解决方案1】:

我的建议是将UIAlertView 替换为其他内容。 TTAlertViewSDCAlertView 都在积极开发中,应该允许您以任何您需要的方式灵活地对视图进行子类化和/或皮肤化。

【讨论】:

    【解决方案2】:

    我同意其他人的观点,即您应该考虑创建自己的警报视图替换。也就是说,这里有一些使用UIAlertView 的选项。

    1) 不要使用原生的UIAlertView 按钮(取消/提交)。相反,将您自己的按钮合并到您的附件视图中,并在没有任何按钮的情况下配置 UIAlertView 本身。现在你可以完全控制了。但是您的按钮看起来与本机警报视图按钮不完全相同,因为您无法将它们放置在正确的位置。

    2) 在点击提交按钮后,您可以尝试禁用提交按钮,直到整个表单得到验证,而不是验证用户的输入。也就是说,保持提交按钮处于禁用状态,直到它通过验证。问题在于UIAlertView 中用于禁用/启用提交按钮的功能非常有限。如果您使用UIAlertView 的原生UIAlertViewPlainTextInputStyle,您会注意到您可以通过委托回调alertViewShouldEnableFirstOtherButton: 启用/禁用提交按钮。

    我能够在此行为的基础上构建并根据我自己的 UITextField 在附件视图中启用/禁用提交按钮(使用UIAlertViewDefaultStyle 时)。有一个很好的论点是不要使用这种技术,因为它使用未记录的机制非常边缘化。 (好吧,这几乎超出了界限......)。但为了完整起见,这是我的解决方案:

    注意,TSAlertViewFormControllerUIViewController,其视图用作 UIAlertViewaccessoryView。您需要确保视图控制器本身(不仅仅是它的视图)在与包含它的 UIAlertView 相同的时间内保持活动状态。另外,你需要在其上设置弱alertView属性!

    @interface TSAlertViewFormController () <UIAlertViewDelegate>
    @end
    
    @implementation TSAlertViewFormController
    {
        IBOutlet UITextField*    _textField;
    }
    
    - (BOOL) alertViewShouldEnableFirstOtherButton:(UIAlertView *)alertView;
    {
        // validate all your fields here!
    
        return [_textField.text isEqualToString: @"abc"];
    }
    
    - (void) setAlertView:(UIAlertView *)alertViewHost
    {
        [self view];
    
        _alertView = alertViewHost;
    
        // sniff out the selector used to handle textfield editing events
        // this could (should!) be considered "undocumented" behavior
        // (one major issue is we assume the target is the UIAlertView itself!)
        UIAlertView* avtemp = [UIAlertView new];
        avtemp.alertViewStyle = UIAlertViewStylePlainTextInput;
        UIControl* avtempTextField = [avtemp textFieldAtIndex: 0];
    
        NSArray* actions = [avtempTextField actionsForTarget: avtemp forControlEvent: UIControlEventEditingChanged];
        if ( actions.count > 0 )
        {
            SEL action = NSSelectorFromString( actions.lastObject );
    
            // route our text field editing-changed events to the host alert view
            // do this for each textfield!
            [_textField addTarget: self.alertView action: action forControlEvents: UIControlEventEditingChanged];
        }
        else
        {
            // need to fail gracefully here...
        }
    }
    
    @end
    

    它的使用方法如下:

    @implementation TSViewController
    {
        TSAlertViewFormController* _avc;
    }
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        _avc = [self.storyboard instantiateViewControllerWithIdentifier: @"avc"];
        _avc.view.frame = CGRectMake(0, 0, 200, 300);
    
        UIAlertView* av = [[UIAlertView alloc] initWithTitle: nil
                                                     message: nil
                                                    delegate: _avc
                                           cancelButtonTitle: @"Cancel"
                                           otherButtonTitles: @"Submit", nil];
    
        _avc.alertView = av;
    
        [av setValue: _avc.view forKey: @"accessoryView"];
        [av show];
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-02-05
      • 1970-01-01
      • 2014-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-18
      • 1970-01-01
      相关资源
      最近更新 更多