在当前上下文中呈现ViewController是模态的,无法正确旋转

时间:2018-07-29 10:32:57

标签: ios swift overlay viewcontroller popover

这是与iOS 11.4,Swift 4和XCode 9一起使用的。

我试图在当前上下文中呈现一个视图控制器,以便使基础上下文变暗但仍可见。我使用以下代码执行此操作:

let storyboard = UIStoryboard(name: "Main", bundle: nil)l
let vc = storyboard.instantiateViewController(withIdentifier: "LoginView") as! LoginViewController
vc.modalPresentationStyle = .overCurrentContext
vc.modalTransitionStyle   = .coverVertical

present(vc, animated: true, completion: nil)

let ppc = vc.popoverPresentationController

ppc?.sourceView = tableView
ppc?.sourceRect = tableView.bounds
ppc?.delegate = vc

LoginViewController在主视图中居中放置一个视图(popview),其中包含我的可编辑控件。 最初可以正常运行,但是我遇到了一些问题:

  1. 所提供的viewcontroller表现为模态。即我无法通过在外部弹出视图中单击来消除它。正如我所假定的,这是因为呈现的视图控制器视图从未收到触摸事件,因为它们被呈现的视图所捕获。
  2. 在设备旋转到仅横向显示屏幕时,LoginViewController的变暗视图填充了屏幕。

我试图通过对LoginViewController的主视图使用通道视图来解决问题1,

override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView?
{
    let view = super.hitTest(point, with: event)
    return view == self ? nil : view
}

这没有帮助。 我可以在主视图上使用UITapGestureRecognizer,如果触摸不与popview配合使用,则从那里调用dismiss,但这对我来说似乎很笨拙,我想知道是否有更好的方法。

我不知道如何解决问题2。我尝试了UIPopoverPresentationController的委托函数,但这不起作用,因为 当我使用.overCurrentContext时,vc.popoverPresentationController始终为零。

当我将modalPresentationStyle设置为.popover时,我会得到popoverPresentationController的值,但是LoginView会完全覆盖呈现的控制器视图。

1 个答案:

答案 0 :(得分:0)

经过进一步的挖掘,我最终找到了问题2的解决方案,以Android方式进行:

展示视图控制器中,我添加了以下功能:

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?)
{
    if (loginViewController != nil)
    {
        present(loginViewController!, animated:false, completion: nil)
    }
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)
{
    super.viewWillTransition(to: size, with: coordinator)

    loginViewController!.dismiss(animated: false, completion: nil)

}

因此,当收到方向更改时,首先关闭弹出视图,并且在执行更改后再次显示弹出窗口。由于在此过程中显示的视图控制器不受损害,因此即使已输入到显示的视图控制器控件中的数据也会保留。

要解决问题1,我在显示的视图控制器中添加了

override func viewDidLoad()
{ 
    super.viewDidLoad()

    let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(sender:)))
    view.addGestureRecognizer(tapGesture)
}

@objc func handleTap(sender: UITapGestureRecognizer)
{
    let touchpoint = sender.location(in: view)
    let popviewrect = popview.frame

    if (!popviewrect.contains(touchpoint))
    {
        dismiss(animated: true, completion: nil)
        delegate?.onDismissed()
    }      
}

演示控制器实现 onDismissed 委托:

func onDismissed()
{
    loginViewController = nil
}

仍然想知道是否还有更优雅的方法