我有一个根视图控制器,它有两个子视图控制器,可以作为子项添加到根目录中.当这些子视图控制器呈现视图控制器时,我希望演示文稿是当前上下文,以便当从视图中删除正在呈现的子节点并且取消分配时,所呈现的模态也将被移除.此外,如果子A呈现视图控制器,我会期望子B的’presentViewController’属性在“当前上下文”演示中为零,即使A仍然呈现.
当我将我呈现的视图控制器的modalPresentationStyle设置为overCurrentContext,并且子视图控制器将definesPresentationContext设置为true时,一切都按预期工作.
如果我将modalPresentationStyle设置为custom并覆盖shouldPresentInFullscreen在我的自定义演示控制器中返回false,那么当我期望它时,这不起作用.
这是一个说明问题的示例:
import UIKit final class ProgressController: UIViewController { private lazy var activityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: .white) private lazy var progressTransitioningDelegate = ProgressTransitioningDelegate() // MARK: Lifecycle override init(nibName nibNameOrNil: String?,bundle nibBundleOrNil: Bundle?) { super.init(nibName: nibNameOrNil,bundle: nibBundleOrNil) setup() } required public init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) setup() } override public func viewDidLoad() { super.viewDidLoad() view.backgroundColor = UIColor(white: 0,alpha: 0) view.addSubview(activityIndicatorView) activityIndicatorView.startAnimating() } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) } override public func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() activityIndicatorView.center = CGPoint(x: view.bounds.width/2,y: view.bounds.height/2) } // MARK: Private private func setup() { modalPresentationStyle = .custom modalTransitionStyle = .crossDissolve transitioningDelegate = progressTransitioningDelegate } } final class ProgressTransitioningDelegate: NSObject,UIViewControllerTransitioningDelegate { func presentationController(forPresented presented: UIViewController,presenting: UIViewController?,source: UIViewController) -> UIPresentationController? { return DimBackgroundPresentationController(presentedViewController: presented,presenting: source) } } final class DimBackgroundPresentationController: UIPresentationController { lazy var overlayView: UIView = { let v = UIView() v.backgroundColor = UIColor(white: 0,alpha: 0.5) return v }() override var shouldPresentInFullscreen: Bool { return false } override func presentationTransitionWillBegin() { super.presentationTransitionWillBegin() overlayView.alpha = 0 containerView!.addSubview(overlayView) containerView!.addSubview(presentedView!) if let coordinator = presentedViewController.transitionCoordinator { coordinator.animate(alongsideTransition: { _ in self.overlayView.alpha = 1 },completion: nil) } } override func containerViewDidLayoutSubviews() { super.containerViewDidLayoutSubviews() overlayView.frame = presentingViewController.view.bounds } override func dismissalTransitionWillBegin() { super.dismissalTransitionWillBegin() let coordinator = presentedViewController.transitionCoordinator coordinator?.animate(alongsideTransition: { _ in self.overlayView.alpha = 0 },completion: nil) } } class ViewControllerA: UIViewController { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) definesPresentationContext = true let vc = ProgressController() self.present(vc,animated: true) { } } } class ViewController: UIViewController { let container = UIScrollView() override func viewDidLoad() { super.viewDidLoad() container.frame = view.bounds view.addSubview(container) let lhs = ViewControllerA() lhs.view.backgroundColor = .red let rhs = UIViewController() rhs.view.backgroundColor = .blue addChildViewController(lhs) lhs.view.frame = CGRect(x: 0,y: 0,width: view.bounds.width,height: view.bounds.height) container.addSubview(lhs.view) lhs.didMove(toParentViewController: self) addChildViewController(rhs) rhs.view.frame = CGRect(x: view.bounds.width,height: view.bounds.height) container.addSubview(rhs.view) rhs.didMove(toParentViewController: self) container.contentSize = CGSize(width: view.bounds.width * 2,height: view.bounds.height) } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) // let rect = CGRect(x: floor(view.bounds.width/2.0),height: view.bounds.height) // container.scrollRectToVisible(rect,animated: true) } }
>这将显示一个ViewController,其滚动视图包含两个子视图控制器
>左侧的红色视图控制器将显示应在当前上下文中显示的进度视图控制器.
>如果视图控制器在“当前上下文”中正确显示,那么您将能够滚动滚动视图,如果您选中了蓝色右侧视图控制器的“presentsViewController”属性,则它应该为零.这些都不是真的.
如果将ProgressController上的setup()函数更改为:
private func setup() { modalPresentationStyle = .overCurrentContext modalTransitionStyle = .crossDissolve transitioningDelegate = progressTransitioningDelegate }
演示文稿/视图层次结构将按预期运行,但不会使用自定义演示文稿.
Apple的shouldPresentInFullscreen文档似乎表明这应该有效:
The default implementation of this method returns true,indicating
that the presentation covers the entire screen. You can override this
method and return false to force the presentation to display only in
the current context.If you override this method,do not call super.
我在iOS 10上的Xcode 8和iOS 11上的Xcode 9中进行了测试,上述代码在任何一种情况下都无法正常工作.