PopOverController自定义尺寸与sourceRect对BarButtonItem不生效的问题
问题描述
在导航栏添加系统样式刷新按钮后,点击按钮需要弹出带表视图的Popover控制器,当前实现存在两处异常:
- 无法正确结合BarButtonItem配置PopoverController的sourceRect,弹出锚点位置偏移
- 弹出的表视图以全屏形式展示,不符合预先设置的200x200自定义尺寸要求
现有问题实现代码
let button = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.refresh, target: self, action: #selector(displayClassRooms(_:))) navigationItem.rightBarButtonItem = button @objc private func displayClassRooms(_ sender: UIBarButtonItem) { let popController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ClassRoomVC") popController.modalPresentationStyle = UIModalPresentationStyle.popover popController.popoverPresentationController?.sourceView = self.view popController.popoverPresentationController?.permittedArrowDirections = .up popController.popoverPresentationController?.sourceRect = CGRect.init(x: 300, y: 0, width: 50, height: 180 ) popController.preferredContentSize = CGSize.init(width: 200, height: 200) present(popController, animated: true, completion:nil) } func adaptivePresentationStyleForPresentationController(controller: UIPresentationController) -> UIModalPresentationStyle { return .none }
问题场景截图

根因与修复方案
1. Popover锚点位置配置错误
原来的实现手动硬编码sourceRect的x坐标为300,既没有适配不同设备的导航栏宽度差异,也没有利用系统为UIBarButtonItem提供的自动锚定能力,永远无法精准匹配右侧按钮的位置。
正确配置方式是给popoverPresentationController直接设置barButtonItem属性为触发事件的sender,系统会自动匹配对应的sourceView、sourceRect,不需要手动计算坐标。
2. 弹出控制器被自动适配为全屏
原来的适配方法存在两个问题,完全没有生效:
- 没有把当前视图控制器绑定为
popoverPresentationController的delegate,方法根本不会被系统调用 - 用的是iOS13之前的旧方法签名,新系统上无法被识别
系统默认在iPhone竖屏环境下,会自动把popover样式转换为全屏modal展示,直接忽略设置的preferredContentSize。修复时需要将当前VC设置为popover的代理,使用新的方法签名返回.none,阻止自动全屏行为。
修复后代码
let button = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.refresh, target: self, action: #selector(displayClassRooms(_:))) navigationItem.rightBarButtonItem = button @objc private func displayClassRooms(_ sender: UIBarButtonItem) { let popController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ClassRoomVC") popController.modalPresentationStyle = .popover // 直接绑定barButtonItem作为锚点,自动匹配正确的sourceRect/sourceView guard let popPC = popController.popoverPresentationController else { return } popPC.barButtonItem = sender popPC.permittedArrowDirections = .up // 绑定代理阻止自动适配为全屏 popPC.delegate = self popController.preferredContentSize = CGSize(width: 200, height: 200) present(popController, animated: true) } // 遵循UIPopoverPresentationControllerDelegate协议,返回.none阻止全屏适配 extension YourViewController: UIPopoverPresentationControllerDelegate { func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle { return .none } }
内容的提问来源于stack exchange,提问作者konya
相关产品推荐
相关产品推荐

