当用户在 iOS Swift 中向下拖动模式时捕获

Catch when user drags down modal in iOS Swift

我试图获得与 Apple 在其 iOS15 日历应用程序中所做的相同的行为(可能在早期版本中也是如此),如果您尝试关闭视图,您将看到一个 操作 Sheet 询问您是否要放弃更改。

所以我想要的是能够以某种方式捕捉到用户试图向下拖动视图的事件,例如检查:

if hasChanges {
// Show Action sheet & stop view from disappearing 
}

这不起作用,因为我不想在 viewWillDisappear 中使用,因为在我开始呈现操作之前视图就消失了 Sheet

如Apple的docs所述,您可以实现UIAdaptivePresentationControllerDelegate并使用presentationControllerDidAttemptToDismiss(_ :)来“拦截”下拉动作。

这是一个简单的示例:

class ConfirmDismissViewController: UIViewController, UIAdaptivePresentationControllerDelegate {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.backgroundColor = .systemYellow
        
        // add a dismiss button
        let b = UIButton(type: .system)
        b.setTitle("Dismiss", for: [])
        b.addTarget(self, action: #selector(btnTapped(_:)), for: .touchUpInside)
        b.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(b)
        NSLayoutConstraint.activate([
            b.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            b.centerYAnchor.constraint(equalTo: view.centerYAnchor),
        ])
        
        // this will trigger a call to presentationControllerDidAttemptToDismiss() on drag-down
        isModalInPresentation = true

        presentationController?.delegate = self
    }

    func presentationControllerDidAttemptToDismiss(_ presentationController: UIPresentationController) {
        
        let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
        
        // Only ask if the user wants to save if they attempt to pull to dismiss, not if they tap Cancel.
        alert.addAction(UIAlertAction(title: "Discard Changes", style: .destructive) { _ in
            self.dismiss(animated: true, completion: nil)
        })
        
        alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
        
        present(alert, animated: true, completion: nil)

    }

    @objc func btnTapped(_ sender: Any?) -> Void {
        // dismiss WITHOUT prompt
        dismiss(animated: true, completion: nil)
    }
    
}

当您显示此视图控制器时,用户可以点击“关闭”按钮明确关闭 VC,或者,如果用户向下拖动,系统会提示您。