禁用所呈现视图控制器的交互式解除

问题描述 投票:0回答:8

iOS 13 为模态呈现的视图控制器引入了

modalPresentationStyle
.pageSheet
(及其兄弟
.formSheet
)的新设计......

…我们可以通过向下滑动呈现的视图控制器来关闭这些工作表(交互式关闭)。尽管新的“拉动关闭”功能非常有用,但它可能并不总是令人满意。

问题:我们如何关闭交互式解雇? - 请记住,我们保持演示风格相同。

ios uiviewcontroller uikit modalviewcontroller ios13
8个回答
423
投票

选项 1:

viewController.isModalInPresentation = true

(禁用交互式

.pageSheet
解雇行为是这样的。)

  • 自 iOS 13 起,
    UIViewController
    包含一个名为
    isModalInPresentation
    的新属性,必须将其设置为
    true
    以防止交互式关闭。
  • 它基本上忽略视图控制器边界之外的事件。如果您不仅使用自动样式,还使用
    .popover
    等演示样式,请记住这一点。
  • 此属性默认为
    false

来自官方文档:如果

true
,UIKit 会忽略视图控制器边界之外的事件,并防止视图控制器在屏幕上时交互式关闭。


选项2:

func presentationControllerShouldDismiss(_ presentationController: UIPresentationController) -> Bool {
    return false
}
  • 自 iOS 13 起,
    UIAdaptivePresentationControllerDelegate
    包含一个名为
    presentationControllerShouldDismiss
    的新方法。
  • 仅当所呈现的视图控制器未以编程方式关闭且其
    isModalInPresentation
    属性设置为
    false
    时,才会调用此方法。

提示: 不要忘记分配

presentationController
的代表。但请注意,众所周知,即使只是访问
presentationController
也会导致内存泄漏。


90
投票
  1. 如果您想要与之前的 iOS 版本相同的行为 (< iOS13) like model presentation in fullscreen, just set the presentation style of your destination view controller to

    UIModalPresentationStyle.fullScreen

    let someViewController = \*VIEW CONTROLLER*\
    someViewController.modalPresentationStyle = .fullScreen
    

    如果您使用故事板,只需选择 segua 并从

    Full Screen
    下拉列表中选择
    Presentation

  2. 如果您只想禁用交互式解除并保留新的呈现样式设置

    UIViewController
    属性
    isModalInPresentation
    true

    if #available(iOS 13.0, *) {
        someViewController.isModalInPresentation = true // available in IOS13
    }
    

11
投票

房产

isModalInPresentation
可能会有所帮助。

来自文档:

当您将其设置为

true
时,UIKit 会忽略视图控制器边界之外的事件,并防止视图控制器在屏幕上时交互式关闭。

你可以这样使用它:

let controller = MyViewController()
controller.isModalInPresentation = true
self.present(controller, animated: true, completion: nil)

10
投票

如果您有一些业务逻辑,例如在解雇之前应填写所有字段之类的内容,您应该:

On

ViewDidLoad
如果您的 ViewController 已在导航控制器中呈现:

func viewDidLoad() { 
    self.navigationController?.presentationController?.delegate = self
}

如果没有,只需使用

func viewDidLoad() { 
    self.presentationController?.delegate = self
}

然后实现委托方法:

extension ViewController: UIAdaptivePresentationControllerDelegate {

    func presentationControllerShouldDismiss(_ presentationController: UIPresentationController) -> Bool {
        guard let text = firstName.text, text.isEmpty else { return false }
        guard let text = lastName.text, text.isEmpty else { return false }
        ...
    
        return true
    }

}

5
投票

如果您使用情节提要来布局 UI,我发现在使用导航控制器时禁用此交互式解除的最佳方法是将属性检查器中导航控制器的显示从“自动”更改为“全屏”。然后,导航堆栈中的所有视图控制器都将全屏显示,并且用户无法将其关闭。

Attribute Inspector showing presentation option for the navigation controller


1
投票

Apple 分享了有关它的示例代码在此链接

它按照许多用户的建议使用

isModalInPresentation


0
投票

我很努力地解决这个问题,但解决方案对我有用是我在**主故事板>检查器>演示>全屏**中选择ViewController默认自动更改全屏

这对我来说是工作


-3
投票

所有解决方案都很好,但就我而言,我需要一个停止移动的选项。 所以这是一个代码。

如果您想阻止移动:

self.yourViewController?.presentedView?.gestureRecognizers?[0].isEnabled = false

如果您想畅通移动:

self.yourViewController?.presentedView?.gestureRecognizers?[0].isEnabled = true
© www.soinside.com 2019 - 2024. All rights reserved.