web-dev-qa-db-fra.com

Le gestionnaire UIAlertController est licencié par clic extérieur (IPad)

Avant iOS8, nous utilisions UIActionSheet pour afficher les alertes et nous devons maintenant utiliser UIAlertController.

Lorsque nous utilisions la feuille UIActionSheet, nous pouvions facilement gérer les situations dans lesquelles l'utilisateur cliquait en dehors de la fenêtre contextuelle (ce qui signifie qu'il souhaitait annuler l'opération) en comparant l'objet clickedButtonAtIndex à cancelButtonIndex. dans cette fonction.

Comment pouvons-nous gérer ces situations avec le nouveau UIAlertController? J'ai essayé d'utiliser le bloc "Achèvement" mais il n'a pas de contexte. Y at-il un moyen facile de gérer cela? (autre que "sauvegarder" les états des actions dans une variable générale).

26
Tomer Peled

Vous pouvez ajouter une action avec le style: UIAlertActionStyleCancel et le gestionnaire de cette action est appelé lorsque l'utilisateur appuie en dehors de la fenêtre contextuelle.

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];
}
43
Gareth

La solution qui fonctionne pour UIAlertController avec un style d'alerte. Juste besoin d'ajouter un identifiant de geste à 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];
}
16
nominanza

UITapGestureRecognizer n'a pas fonctionné pour moi alors j'ai utilisé de cette façon:

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
    })
    // ...
}
1
Apoc