web-dev-qa-db-ja.com

UIAlertControllerハンドラーは、外部クリック(iPad)で閉じる

IOS8以前では、アラートを表示するためにUIActionSheetを使用していましたが、UIAlertControllerを使用する必要があります。

UIActionSheetを使用した場合、ユーザーがclickedButtonAtIndexとcancelButtonIndexを比較することで、ユーザーがポップアップの外をクリックした(つまり、操作をキャンセルしたい)状況を簡単に処理できます。この関数で。

これらの状況を新しいUIAlertControllerでどのように処理できますか? 「完了」ブロックを使用しようとしましたが、コンテキストがありません。これを簡単に処理する方法はありますか? (一般的な変数のアクション状態を「保存」する以外)。

26
Tomer Peled

Style: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];
}
44
Gareth

アラートスタイルのUIAlertControllerで機能するソリューション。 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];
}
16
nominanza

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