iOS 17中UIPopoverPresentationController无法保留偏好尺寸问题
iOS 17 中 UIPopoverPresentationController 无法保留内容控制器偏好尺寸的解决方法
问题根源
iOS 17 对 UIPopoverPresentationController 的尺寸计算逻辑做了调整,原有的依赖 view.frame 设置 preferredContentSize 的方式不再可靠,且重复展示弹窗时,控制器复用会导致尺寸被系统缓存的状态重置,出现压缩问题。
具体解决方案
1. 调整内容控制器的尺寸设置逻辑
在 contentVC 的 viewDidLoad 中,不要直接设置 self.view.frame,改为直接指定 preferredContentSize,避免依赖未完成布局的 view 尺寸:
- (void)viewDidLoad { [super viewDidLoad]; // 直接设置偏好尺寸,替代手动设置view.frame self.preferredContentSize = CGSizeMake(320, 480); // 保留原有的边框设置 CALayer *layer = self.view.layer; layer.borderColor = [[UIColor darkGrayColor] CGColor]; layer.borderWidth = 2; layer.cornerRadius = 10; }
2. 优化弹窗展示方法
移除从 contentVC.view.frame 获取尺寸的代码,确保 preferredContentSize 由内容控制器内部管理,或在外部明确指定:
+ (void) showDialogiPad:(UIViewController *)contentVC fromPresentingVC:(UIViewController *)presentingVC inView:(UIView *)view atFrame:(CGRect)frame withDirection:(UIPopoverArrowDirection)direction { contentVC.modalPresentationStyle = UIModalPresentationPopover; // 若需外部控制尺寸,可直接在此设置,否则依赖contentVC内部的preferredContentSize // contentVC.preferredContentSize = CGSizeMake(320, 480); contentVC.popoverPresentationController.sourceRect = frame; contentVC.popoverPresentationController.sourceView = view; contentVC.popoverPresentationController.permittedArrowDirections = direction; [presentingVC presentViewController:contentVC animated:YES completion:nil]; }
3. 解决重复展示的压缩问题
如果复用 contentVC 实例,每次展示前必须重置 preferredContentSize,避免系统复用之前缓存的尺寸状态:
// 复用contentVC时,展示前重新设置尺寸 contentVC.preferredContentSize = CGSizeMake(320, 480); [YourClass showDialogiPad:contentVC fromPresentingVC:presentingVC inView:view atFrame:frame withDirection:direction];
对应观察点的解释
- 首次打开正常、后续压缩:首次展示时 view 布局刚好符合预期尺寸,但复用控制器时,系统会根据之前的布局状态调整尺寸,且未重置
preferredContentSize,导致压缩。 - 注释
preferredContentSize后弹窗最大尺寸:此时系统会自动计算内容所需的最大可用空间,填充弹窗。 - 改用
UIModalPresentationFormSheet尺寸正确:该样式的尺寸计算逻辑更严格遵循preferredContentSize,不受 popover 的自适应布局规则影响。
内容的提问来源于stack exchange,提问作者Silverness
相关产品推荐
相关产品推荐

