Обработчик UIAlertController отклоняется при нажатии снаружи (IPad)
Ранее для iOS8 мы использовали UIActionSheet для отображения предупреждения, и теперь нам нужно использовать UIAlertController.
Когда мы использовали UIActionSheet, мы могли легко справляться с ситуациями, когда пользователь щелкал за пределами всплывающего окна (что означает, что он хочет отменить операцию), сравнивая clickedButtonAtIndex с cancelButtonIndex - если пользователь действительно нажал вне всплывающего окна, мы получили отмените кнопку кнопки в этой функции.
Как мы можем справиться с этими ситуациями с помощью нового UIAlertController? Я попытался использовать блок "завершения", но у него нет никакого контекста. Есть ли простой способ справиться с этим? (кроме "сохранения" состояний действий в некоторой общей переменной).
Ответы
Ответ 1
Вы можете добавить действие со стилем: UIAlertActionStyleCancel и обработчик для этого действия вызывается, когда пользователь выходит за пределы всплывающего окна.
if ([UIAlertController class]) {
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Alert Title" message:@"A Message" preferredStyle:UIAlertControllerStyleActionSheet];
[alertController addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
NSLog(@"User clicked button called %@ or tapped elsewhere",action.title);
}]];
[alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
NSLog(@"User clicked button called %@",action.title);
}]];
[alertController addAction:[UIAlertAction actionWithTitle:@"Other" style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action) {
NSLog(@"User clicked button called %@",action.title);
}]];
UIControl *aControl = (UIControl *) sender;
CGRect frameInView = [aControl convertRect:aControl.bounds toView:self.view];
alertController.popoverPresentationController.sourceRect = frameInView;
alertController.popoverPresentationController.sourceView = self.view;
alertController.popoverPresentationController.permittedArrowDirections = UIPopoverArrowDirectionAny;
[self presentViewController:alertController animated:YES completion:nil];
}
Ответ 2
Решение, которое работает для UIAlertController с типом предупреждения. Просто нужно добавить распознаватель жестов в alertController superview.
[self presentViewController: alertController
animated: YES
completion:^{
alertController.view.superview.userInteractionEnabled = YES;
[alertController.view.superview addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget: self action: @selector(alertControllerBackgroundTapped)]];
}];
- (void)alertControllerBackgroundTapped
{
[self dismissViewControllerAnimated: YES
completion: nil];
}
Ответ 3
UITapGestureRecognizer не работал у меня, поэтому я использовал этот способ:
func addDismissControl(_ toView: UIView) {
let dismissControl = UIControl()
dismissControl.addTarget(self, action: #selector(self.dismissAlertController), for: .touchDown)
dismissControl.frame = toView.superview?.frame ?? CGRect.zero
toView.superview?.insertSubview(dismissControl, belowSubview: toView)
}
func dismissAlertController() {
self.dismiss(animated: true, completion: nil)
}
func presentAlertController(title: String?, message: String?, preferredStyle: UIAlertControllerStyle, handler: ((UIAlertAction) -> Swift.Void)? = nil, completion: (() -> Swift.Void)? = nil) {
let alertController = UIAlertController(title: title, message: nil, preferredStyle: .actionSheet)
alertController.addAction(UIAlertAction(title: "OK", style: .default) { (alertAction) -> Void in
handler?(alertAction)
})
self.present(alertController, animated: true, completion: {
self.addDismissControl(alertController.view)
completion?()
})
}
func someWhereInYourViewController() {
// ...
presentAlertController(title: "SomeTitle", message: "SomeMessage", preferredStyle: .actionSheet, handler: { (alertAction) -> Void in
//do some action
}, completion: {
//do something after presentation
})
// ...
}