如何在WidgetBundle中添加iOS16 Lock Screen Widget并兼容iOS15
编译失败原因
@WidgetBundleBuilder 是苹果为Widget容器实现的结果构建器,原生不支持直接在构建闭包内书写#available版本判断的if-else分支,示例代码中的空else分支和未做可用性包装的高版本Widget,会导致构建器无法正确解析语法,最终触发编译错误。
正确实现方式
核心思路是给仅支持iOS16+的锁屏Widget添加显式系统版本标记,删除WidgetBundle内空的else分支,不需要额外修改项目的iOS15部署目标,参考代码如下:
方案1:封装高版本Widget组(推荐)
// 给仅支持高版本的组件封装一层,添加明确的可用性标记 @available(iOSApplicationExtension 16.0, *) struct LockScreenWidgets: Widget { var body: some WidgetConfiguration { LockScreenRecoveryScoreWidget().body // 后续新增的iOS16+锁屏Widget都可以加在这里 } } struct SecondExtraBundle: WidgetBundle { @WidgetBundleBuilder var body: some Widget { // 原有兼容iOS15的Widget不受影响 DailyHeartRatesWidget() // 版本判断不需要写空else分支,低版本系统会自动忽略该块 if #available(iOSApplicationExtension 16.0, *) { LockScreenWidgets() } } }
方案2:直接给高版本Widget加可用性标记
如果不想额外封装分组,也可以直接给锁屏Widget本身添加系统版本限制:
// 直接对锁屏Widget声明系统版本要求 @available(iOSApplicationExtension 16.0, *) extension LockScreenRecoveryScoreWidget: Widget { } struct SecondExtraBundle: WidgetBundle { @WidgetBundleBuilder var body: some Widget { DailyHeartRatesWidget() if #available(iOSApplicationExtension 16.0, *) { LockScreenRecoveryScoreWidget() } } }
注意事项
- 禁止在
@WidgetBundleBuilder闭包内书写空的else分支,会导致构建器无法匹配对应构建方法 - 所有仅支持iOS16+的组件必须显式标注
@available(iOSApplicationExtension 16.0, *),避免低版本系统链接高版本API触发崩溃 - 不要给整个WidgetBundle的body属性添加高版本可用性标记,会导致原有兼容iOS15的Widget在低版本系统下无法加载
内容的提问来源于stack exchange,提问作者GarySabo
相关产品推荐
相关产品推荐

