自定义警报视图的验证

Posted

技术标签:

【中文标题】自定义警报视图的验证【英文标题】: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 中只保留一个按钮来取消警报。 【参考方案1】:

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

【讨论】:

【参考方案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];

【讨论】:

以上是关于自定义警报视图的验证的主要内容,如果未能解决你的问题,请参考以下文章

如何防止键盘出现在自定义警报视图上

在 Swift 的警报中使用自定义视图

自定义弹出框警报视图

本机真棒警报自定义视图抛出错误

如何在特定时间显示自定义警报?

UItableview 在自定义单元格上使用带有提示的警报视图重新加载数据的问题