Ios 当源视图在Swift中更改时,如何更新popover的布局(位置)?

Ios 当源视图在Swift中更改时,如何更新popover的布局(位置)?,ios,swift,autolayout,uikit,uipopoverpresentationcontroller,Ios,Swift,Autolayout,Uikit,Uipopoverpresentationcontroller,我想更新popover的布局,我已经尝试使用setNeedsLayout()和layoutIfNeeded()方法,但找不到解决方案 我有一个简单的屏幕,有4个按钮称为popover,popover中有2个额外的按钮: 按钮->隐藏按钮3,并向左移动按钮1和按钮2 重新定位->将POPOR的源视图从按钮1/2/3/4(发送器)更改为按钮4。 我遇到的问题是,我无法更新/刷新屏幕,并且弹出框一直指向以前的源代码视图位置。 不知何故,我需要一种更新视图的方法,它比layoutifneed()更强

我想更新popover的布局,我已经尝试使用
setNeedsLayout()
layoutIfNeeded()
方法,但找不到解决方案

我有一个简单的屏幕,有4个按钮称为popover,popover中有2个额外的按钮:

  • 按钮->隐藏按钮3,并向左移动按钮1和按钮2
  • 重新定位->将POPOR的源视图从按钮1/2/3/4(发送器)更改为按钮4。
  • 我遇到的问题是,我无法更新/刷新屏幕,并且弹出框一直指向以前的源代码视图位置。

    不知何故,我需要一种更新视图的方法,它比
    layoutifneed()
    更强大,因为如果屏幕从纵向/横向更改,则弹出窗口会自动更改

    该项目的GitHub

    使用的代码如下所示:

    class ViewController: UIViewController, ButtonDidDisappearDelegate {
    
        @IBOutlet weak var button1: UIButton!
        @IBOutlet weak var button2: UIButton!
        @IBOutlet weak var button3: UIButton!
        @IBOutlet weak var button4: UIButton!
    
        @IBOutlet weak var constrain2: NSLayoutConstraint!
    
        var popVC: PopVC?
    
        override func viewDidLoad() {
            super.viewDidLoad()
        }
    
        @IBAction func buttonPopover(_ sender: UIButton) {
            configureAndPresentPopover(from: sender)
        }
    
        func buttonDisappear() {
            self.constrain2.constant = 100
            self.button3.isHidden = !self.button3.isHidden
    
            if !self.button3.isHidden {
                self.constrain2.constant = 10
            }
        }
    
        func repositionPopover() {
            DispatchQueue.main.async {
                if let popVC = self.popVC {
                    self.self.popoverPresentationController(popVC.popoverPresentationController!, willRepositionPopoverTo: self.button4.bounds, in: self.button4)
                }
                self.view.setNeedsLayout()
                self.view.layoutIfNeeded()
            }
        }
    }
    
    extension ViewController: UIPopoverPresentationControllerDelegate {
    
        func configureAndPresentPopover(from sender: UIButton) {
    
            popVC = storyboard?.instantiateViewController(withIdentifier: "popVC") as? PopVC
    
            guard let popVC = popVC else {
                return
            }
    
            popVC.popOverDelegate = self
            popVC.modalPresentationStyle = .popover
    
            let popOverVC = popVC.popoverPresentationController
            popOverVC?.delegate = self
            popOverVC?.sourceView = sender
            popOverVC?.sourceRect = sender.bounds
            popVC.preferredContentSize = CGSize(width: 300, height: 60)
            popOverVC?.permittedArrowDirections = .down
    
            self.present(popVC, animated: true)
        }
    
        func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
            return .none
        }
    
        func popoverPresentationController(_ popoverPresentationController: UIPopoverPresentationController,
                                           willRepositionPopoverTo rect: CGRect,
                                           in view: UIView) {
            popoverPresentationController.sourceView = view
            popoverPresentationController.sourceRect = rect
        }
    }
    
    以及popover控制器:

    protocol ButtonDidDisappearDelegate: class {
        func configureAndPresentPopover(from sender: UIButton)
        func buttonDisappear()
        func repositionPopover()
    }
    
    class PopVC: UIViewController {
    
        weak var popOverDelegate: ButtonDidDisappearDelegate?
    
        override func viewDidLoad() {
            super.viewDidLoad()
        }
    
    
        @IBOutlet weak var popoverButton: UIButton!
    
        @IBAction func popoverAction(_ sender: Any) {
            popOverDelegate?.buttonDisappear()
            DispatchQueue.main.async {
                self.view.setNeedsLayout()
                self.view.layoutIfNeeded()
            }
        }
    
        @IBAction func reposition(_ sender: Any) {
            popOverDelegate?.repositionPopover()
        }
    }
    

    您需要指定箭头的新位置,并要求显示控制器视图的布局,而不仅仅是显示的视图

    尝试:


    您可以再次尝试设置sourceview和sourcerect。更改sourcview边界时调用此函数

    func repositionPopover() {
        let popOverController = presentedViewController?.presentationController as? UIPopoverPresentationController
        popOverController?.sourceView = button4
        popOverController?.containerView?.setNeedsLayout()
        popOverController?.containerView?.layoutIfNeeded()
    }