防止 UIAlertController 关闭

Prevent UIAlertController to dismiss

我想阻止 UIAlertController 解雇。

我有一个 UIAlertAction,它只是将一个字符串附加到 UIAlertTextField 中,但是,一旦点击它就会关闭视图控制器 [不需要]。我试过添加一个 NSNotification,结果不理想。

    UIAlertAction *pasteMessage = [UIAlertAction actionWithTitle:@"Paste Message" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
        UITextField *textField = alertC.textFields.firstObject;
        textField.text = [textField.text stringByAppendingString:[NSString stringWithFormat:@"%@", copiedString]];
    }];

我还尝试通过以下方式设置否以粘贴消息:

 [alertC canPerformAction:@selector(dismissViewControllerAnimated:completion:) withSender:pasteMessage];

-(void)dismissViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion {
    UIAlertController *alertController = (UIAlertController *)self.presentedViewController;
    UIAlertAction *paste = alertController.actions.firstObject;
       if (paste) {
         flag = NO;
       } else {
         flag = YES;
       }
 }

编辑,我不是要阻止 UIAlertAction 的点击,而是要防止 UIAlertController 在点击上述操作时消失。该操作可以是 enabled/disabled 任何内容,但我的目标是通过按下一个操作将复制的消息简单地粘贴到 UITextField 中(因此我不希望它被取消)

我还意识到将 BOOL 设置为 dismissViewControllerAnimated: 只是将其设置为 而不是 动画视图控制器关闭,我不希望它暗示它是为了停止实际解雇过程。简单地提供我已经尝试过的与我的目标相关的事情。我还尝试在选择 pasteMessage 时显示 new UIAlertController 自动填充 new UIAlertControllers 文本字段消息,它有效,但我觉得它对于可以完成的事情来说太老套了。

编辑:更新为 Swift 5

编辑:已更新以包含@skywalker 的反馈

所以我真的让它起作用了。简而言之,它涉及向 UIAlertController 添加一个长按手势识别器,在关闭之前触发。

首先,在您的视图控制器中为您的 UIAlertController 和您要防止触发的 UIAlertAction 创建延迟加载的计算变量,以便可以通过手势识别器的选择器访问 self您将附加到警报的方法(选择器中的self暗示所有这些都在视图控制器中)。

lazy var alert: UIAlertController = {

    let alert = UIAlertController(title: "Title", message: "Message", preferredStyle: .alert)

    alert.addTextField(configurationHandler: nil)

    let appendAction = self.appendAction
    let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)

    alert.addAction(appendAction)
    alert.addAction(cancelAction)

    let gestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(append(sender:)))
    gestureRecognizer.minimumPressDuration = 0.0
    alert.view.addGestureRecognizer(gestureRecognizer)

    return alert
}()

lazy var appendAction: UIAlertAction = {
    return UIAlertAction(title: "Paste Message", style: .default, handler: nil)
}()

确保你上面的手势识别器是一个 UILongPressGestureRecognizer 设置的最小按下持续时间为 0。这样你就可以在动作被触发之前访问手势状态(当用户按下时)完全。在那里你可以禁用 UIAlertAction,实现你的自定义代码,并在手势完成后重新启用动作(用户已经触摸)。见下文:

@objc func append(sender: UILongPressGestureRecognizer) {
    
    switch sender.state {
    case .began:
        appendAction.isEnabled = false
    case .ended:
        // Do whatever you want with the alert text fields
        print(alert.textFields?[0].text)
        appendAction.isEnabled = true
    default:
        return
    }
}

此外,确保拥有此警报呈现的视图控制器符合 UIGestureRecognizerDelegate 以识别同步手势。

extension YourViewController: UIGestureRecognizerDelegate {

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
}

然后,只要出示UIAlertController就可以了。

func showAlert() {
    self.present(alert, animated: true, completion: nil)
}

这显然是一个 hack,但我知道没有其他方法可以在没有 hack 的情况下实现这一点,因为它不是要实现的。例如,手势识别器与 UIAlertController 相关联,因此用户可以在点击警报上的任意位置(取消按钮除外)时触发该方法。

原始答案:

这是我能想到的最接近黑客攻击的回合了。如果有某种方法可以将关闭过渡时间自定义为空,那么您可以将 animated: 设置为 false,它看起来就像是相同的警报,但我认为这是不可能的

class ViewController: UIViewController {

    @IBAction func alert(sender: AnyObject) {
        let alert = UIAlertController(title: "title", message: "message", preferredStyle: .Alert)
    
        alert.addTextFieldWithConfigurationHandler(nil)
    
        let appendAction = UIAlertAction(title: "Append text", style: .Default) { _ in
            var textField = alert.textFields![0] as UITextField
            // Append text here
            self.presentViewController(alert, animated: true, completion: nil)
        }
    
        let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel, handler: nil)
    
        alert.addAction(appendAction)
        alert.addAction(cancelAction)
    
        self.presentViewController(alert, animated: true, completion: nil)
    }
}

我只熟悉swift

回答了几乎相同的问题here

警报中的文本字段支持粘贴选项,因此没有真正的理由在警报中使用单独的按钮来指示 "paste" 选项。

否则你应该模仿 UIAlertController 并用 desiread 行为重新实现它。