自定义警报视图的验证
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
时)。有一个很好的论点是不要使用这种技术,因为它使用未记录的机制非常边缘化。 (好吧,这几乎超出了界限......)。但为了完整起见,这是我的解决方案:
注意,TSAlertViewFormController
是 UIViewController
,其视图用作 UIAlertView
的 accessoryView
。您需要确保视图控制器本身(不仅仅是它的视图)在与包含它的 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];
【讨论】:
以上是关于自定义警报视图的验证的主要内容,如果未能解决你的问题,请参考以下文章