当iPad旋转时,ActionSheet的PopoverController不会停留在窗口的中心

时间:2018-05-04 17:45:28

标签: ios swift ipad uiactionsheet

我有一个logOut按钮,它使用以下代码显示一个操作表,该操作表直接在窗口中间将iPad上的popover居中:

popoverController.sourceRect = CGRect(x: window.bounds.midX, y: window.bounds.midY, width: 0, height: 0)
popoverController.permittedArrowDirections = []

这里显示在窗口中间:

Center

但是当我旋转iPad时,它会将自己定位在左下角:

Lower left hand corner

为什么每当我旋转iPad时它都不会停留在窗口的中央?如何修复它以使其保持旋转中心?

ActionSheet:

fileprivate func logOut(){

    let actionSheet = UIAlertController(title: nil, message: "Are you sure you want to log out?", preferredStyle: .actionSheet)

    let cancelActionButton = UIAlertAction(title: "Cancel", style: .destructive){ (action) in
        // ...
    }

    let logoutActionButton = UIAlertAction(title: "Log Out", style: .default){ (action) in
         // ...
     }

    actionSheet.addAction(logoutActionButton)
    actionSheet.addAction(cancelActionButton)

    if let popoverController = actionSheet.popoverPresentationController{
        popoverController.popoverBackgroundViewClass = PopoverBackgroundView.self

        popoverController.sourceView = view
        guard let window = UIApplication.shared.keyWindow else {
            popoverController.sourceView = view
            popoverController.sourceRect = CGRect(x: view.bounds.midX, y: view.bounds.midY, width: 0, height: 0)
            popoverController.permittedArrowDirections = []
            return
        }
        window.backgroundColor = .clear
        popoverController.sourceRect = CGRect(x: window.bounds.midX, y: window.bounds.midY, width: 0, height: 0)
        popoverController.permittedArrowDirections = []
    }
    tabBarController?.present(actionSheet, animated: true, completion: nil)
}

UIPopoverBackgroundView的子类:

class PopoverBackgroundView: UIPopoverBackgroundView {

    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = UIColor.white
    }

    convenience required init(coder aDecoder: NSCoder) {
        self.init(frame: CGRect.zero)
    }

    override func layoutSubviews() {
        super.layoutSubviews()
    }

    override var arrowOffset: CGFloat {
        get {
            return 0.0
        }
        set {
        }

    }

    override var arrowDirection: UIPopoverArrowDirection {
        get {
            return UIPopoverArrowDirection.up
        }
        set {
        }
    }

    override class func contentViewInsets() -> UIEdgeInsets {
        return UIEdgeInsetsMake(10.0, 10.0, 10.0, 10.0)
    }

    override class func arrowBase() -> CGFloat {
        return 0.0
    }

    override class func arrowHeight() -> CGFloat {
        return 0.0
    }

    override class var wantsDefaultContentAppearance: Bool {
        get {
            return false
        }
    }
}

3 个答案:

答案 0 :(得分:2)

您应该在旋转设备时更新相框:

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    let bounds = UIApplication.shared.keyWindow?.bounds ?? view.bounds
    currentActionSheet?.popoverPresentationController?.sourceRect = CGRect(x: bounds.midX, y: bounds.midY, width: 0, height: 0)
}

您需要将UIAlertController或popoverController保存到变量

weak var currentActionSheet : UIAlertController?

答案 1 :(得分:0)

使用@omarzi答案的一部分,我可以在使用此SO Answer

进行梳理时将其付诸实践

就像奥马尔齐说的那样,我必须创建一个变量来跟踪行动表:

var actionSheet: UIAlertController?

然后在我的logOut()函数中,我将其初始化为我在那里创建的操作表:

fileprivate func logOut(){

    self.actionSheet = UIAlertController(title: nil, message: "Are you sure you want to log out?", preferredStyle: .actionSheet)
    //... everything else

最后我使用了上面链接的SO答案,就像omarzi的建议一样,它建议在设备旋转时更新帧,而是答案说要在viewDidLayoutSubviews()更新它,如下所示:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    if let window = UIApplication.shared.keyWindow{
        actionSheet?.popoverPresentationController?.sourceRect = CGRect(x: window.bounds.midX, y: window.bounds.midY, width: 0, height: 0)
    }
}
奥马尔齐的回答让我朝着正确的方向前进。我没有选择它作为正确答案,因为当我将actionSheet变量声明为weak时,当我尝试在logOut()函数中初始化它时,actionSheet变量保持nil并且不会初始化。此外,当我在override函数上尝试viewWillTransition时,出现了错误“

  

Method不会覆盖其超类“

中的任何方法

当我从override移除viewWillTransition时,它就不会被调用。

由于我遇到的问题,我没有接受她/他的答案作为公认的答案,但是我向她/他做出了投票,使我朝着正确的方向前进。谢谢omarzi!

答案 2 :(得分:0)

我可以使用这种方法解决问题

open override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()
        if let window = UIApplication.shared.keyWindow {
            popoverPresentationController?.sourceRect = CGRect(x: window.bounds.midX, y: window.bounds.midY, width: 0, height: 0)
        }
}

在我的UIAlertController扩展中。