ios - example - ui alert controller swift 4
Controlador UIAlertController descartar al hacer clic fuera(IPad) (3)
La solución que funciona para UIAlertController con estilo de alerta. Solo necesitaba agregar el reconocedor de gestos a la superview alertController.
[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];
}
Antes de iOS8 usamos UIActionSheet para mostrar alertas y ahora tenemos que usar el UIAlertController.
Cuando usamos UIActionSheet, podíamos manejar fácilmente situaciones en las que el usuario hacía clic fuera del menú emergente (lo que significa que desea cancelar la operación) comparando el clickedButtonAtIndex con el cancelButtonIndex; si el usuario efectivamente presionó fuera del menú emergente obtenemos el botón cancelar índice en esta función.
¿Cómo podemos manejar estas situaciones con el nuevo UIAlertController? Traté de usar el bloque "finalización" pero no tiene ningún contexto. ¿Hay una manera fácil de manejar esto? (aparte de "guardar" los estados de las acciones en alguna variable general).
Puede agregar una acción con estilo: UIAlertActionStyleCancel y se llama al controlador para esta acción cuando el usuario toca fuera de la ventana emergente.
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];
}
UITapGestureRecognizer no funcionó para mí, así que lo he usado de esta manera:
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
})
// ...
}