在iOS 16.4中,苹果为SwiftUI引入了.presentationSizing(_:)修饰符,声称能让Sheet根据内容“自动调整大小”。其中.fitted模式尤其被寄予厚望——开发者只需一句代码,就能让弹出窗口完美贴合内容,不再手动设定frame或使用.presentationDetents。然而,这个“自动”究竟有多智能?经过一线开发者的反复测试,真相可能并不如想象中美好。

官方描述:理想化的“自适应”

根据苹果文档,.presentationSizing(.fitted)会“调整Sheet的大小以适应其呈现的内容”。在WWDC 2023的相关session中,工程师演示了一个简单的文本输入界面,Sheet确实紧紧包裹住了输入框和按钮。这让许多开发者以为,从此告别了计算高度、适配滚动内容的繁琐工作。

但实际开发环境远比演示复杂。当内容包含动态文本、图片、列表甚至异步加载的视图时,.fitted的表现立刻暴露出局限性。

实测:三大场景下的真实表现

为了验证真相,我针对常见场景进行了对比测试,环境为Xcode 15.2 + iOS 17.2模拟器与真机。

场景一:纯静态单行文本
当Sheet内仅有一个Text视图时,.fitted确实完美自适应:Sheet高度等于文本行高,左右边缘与内容齐平。这与文档描述一致。

场景二:可滚动列表
ListScrollView放入Sheet,.fitted并未像预期那样“收缩”到第一屏内容大小。相反,它默认将Sheet高度设为列表的内容总高度,若列表超过屏幕高度,则直接占满全屏。这意味着当内容可滚动时,“自适应”退化为“要么完整显示,要么占满”,失去了预期中的弹性。

场景三:动态加载内容
网络请求后更新Sheet内的VStack(例如加载用户个人信息)。.fitted在内容变化后并不会自动重新计算尺寸。必须触发Sheet的重新展示(例如dismisspresent)才能更新高度。对于实时反馈的交互场景,这几乎不可接受。

隐藏的“安全区域”陷阱

进一步测试发现,.fitted会将安全区域(如导航栏、Home Indicator区域)计入大小计算。如果Sheet底部内容被安全区域遮挡,.fitted可能产生不合理的空白或裁剪。开发者不得不在内容外包裹额外padding来矫正,这恰恰违背了“自动”的初衷。

社区反馈:褒贬不一,但共识明确

在Swift论坛和Stack Overflow上,该功能引发大量讨论。知名iOS开发者Paul Hudson在其博客中指出:“.fitted更适合固定内容,对动态UI几乎不可用。”另一位社区成员@iOSDevChris分享了一个经验:改用.preferred模式并配合GeometryReader手动计算高度,反而更可靠。

事实上,苹果自己也留了后路——.presentationSizing还提供了.formSheet.pageSheet等模式,开发者可以根据需求选择。但.fitted作为“智能”担当,显然未能兑现承诺。

结论:可以期待,但别依赖

客观来说,.presentationSizing(.fitted)对于高度固定的简单UI(如弹窗、确认框、短表单)确实能减少代码量。然而,一旦涉及可滚动内容、动态加载或安全区域交互,它几乎必然失效。建议开发者采取混合策略:普通场景直接使用.fitted,复杂场景回退到.presentationDetents配合.height(estimated:)手动控制。苹果虽然在持续改进SwiftUI,但“完全自动化”的Sheet尺寸调整,目前仍是近在咫尺却触不可及的愿景。