PopoverController из ActionSheet не остается в центре окна при повороте iPad - PullRequest
0 голосов
/ 04 мая 2018

У меня есть кнопка выхода из системы, которая представляет лист действий, который центрирует всплывающее окно на iPad прямо в середине окна, используя этот код:

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
        }
    }
}

Ответы [ 2 ]

0 голосов
/ 04 мая 2018

Используя часть ответа @omarzi, я смог заставить его работать, комбинируя его с этим SO Ответом

Как сказал Омарци, мне нужно было создать переменную для отслеживания листа действий:

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, с которым я столкнулся выше, который, как и предложение Омарци, предлагал обновить кадр при повороте устройства, но вместо этого в ответе было сказано обновить его в 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, я получил сообщение об ошибке "

Метод не переопределяет любой метод из своего суперкласса "

Когда я удалил override из viewWillTransition, он не был вызван.

Я не принял ее / его ответ в качестве принятого ответа из-за проблем, которые у меня были, но я выразил ей / ей признательность за то, что направил меня в правильном направлении. Спасибо, Омарци!

0 голосов
/ 04 мая 2018

Вы должны обновить кадр, когда устройство поворачивается:

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?
...