You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

兼容iOS15适配iOS16小组件时WidgetBundle无法使用#available问题

@WidgetBundleBuilder 不支持在构建闭包内直接使用if #available做版本分支判断,这是WidgetKit的固有API限制:只要在闭包内直接写入RememberAccWidget()初始化代码,即使外层包裹版本判断,低版本系统运行时仍会尝试加载这个仅支持iOS16的类,触发编译报错或运行时崩溃。

适配方案

把iOS16专属的组件收拢到单独标记了16+可用性的WidgetBundle中,在主WidgetBundle里通过版本判断返回对应分支即可,调整后的代码如下:

@main
struct RememberWidgetBundle: WidgetBundle {
    @WidgetBundleBuilder
    var body: some Widget {
        // 注意使用iOSApplicationExtension的版本判断,匹配Widget扩展的运行环境
        if #available(iOSApplicationExtension 16.0, *) {
            iOS16WidgetCollection()
        }
        RememberWidget()
    }
}

// iOS16+专属组件集合,仅在16以上系统才会被加载
@available(iOSApplicationExtension 16.0, *)
struct iOS16WidgetCollection: WidgetBundle {
    var body: some Widget {
        RememberAccWidget()
        // 后续新增的iOS16专属锁屏组件、实时活动相关组件都可以放在这里
    }
}

// 原有的RememberAccWidget、RememberWidget代码不需要做任何修改
@available(iOS 16, *)
struct RememberAccWidget: Widget {
    let kind: String = "Remember Accessory 1"

    var body: some WidgetConfiguration {
        StaticConfiguration(kind: kind, provider: Provider()) { entry in
            RememberAccWidgetEntryView(entry: entry)
        }
        .configurationDisplayName("Accessory Widget")
        .description(helpText)
        .supportedFamilies([.accessoryInline, .accessoryRectangular])
    }
}
实现逻辑说明
  • 所有iOS16专属组件的初始化代码,都放在被@available(iOSApplicationExtension 16.0, *)标记的iOS16WidgetCollection内部,低版本系统完全不会加载这段代码路径,从根本上避免了找不到类的崩溃
  • 主WidgetBundle没有加任何版本限制,全系统版本都能正常初始化
  • 版本判断使用iOSApplicationExtension 16.0而非普通的iOS 16,匹配Widget扩展的运行环境,避免版本判断失效

适配后可完全达到预期效果:iOS15系统仅加载原有桌面小组件,功能完全不受影响;iOS16系统同时加载原有桌面小组件和新增的锁屏配件小组件,两类组件都能正常展示使用。

内容的提问来源于stack exchange,提问作者Lim Thye Chean

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 03:12:23