在尝试将带参数的 @ViewBuilder闭包的参数设为可选时,如何消除“无法在推断时使用默认表达式”的警告?

移动开发 2026-07-10

我在应用中有一个常见模式,在其中我在一个泛型Struct中定义一个@ViewBuilder闭包,以使它可选地被使用:

struct MenuList<T: MenuListItem, AdditionalRowActions: View>: View
{
    private var additionalRowActions: (T, Binding<Bool>) -> AdditionalRowActions

    init(@ViewBuilder additionalRowActions: @escaping (T, Binding<Bool>) -> AdditionalRowActions = { (_: T, _: Binding<Bool>) in EmptyView() })
    {
        self.additionalRowActions = additionalRowActions
    }
}

在我安装Xcode 26.4之后,我现在在该参数上收到以下警告:

无法使用默认表达式来推断 '(T, Binding) -> AdditionalRowActions',因为它可以从参数#0、#12、#13、#17、#18、#20、#21、#22、#24、#25推断出来;在未来的Swift语言模式中,这将成为一个错误

所提到的属性(为简洁起见,我在最初的示例中省略了它们)都属于 T[T] 的类型,或者是一个非 @ViewBuilder 闭包,它接收 T 作为参数。

我想知道是否有人知道如何在保持相同功能的前提下消除这个警告?

解决方案

编译器需要能够对结果构建器的每个实例进行专门化,因此在这种实例中你不能使用Swift的某些默认参数特性。

要实现你想要的(可选参数),你需要再创建一个初始化器,使该参数不再是可选的。这样Swift就能恰好选择使用哪一个初始化器,而不是在每个调用点为默认值或传入的初始化值去创建自定义的专门化。

此外,你还需要告诉编译器,这个初始化器只有在 AdditionalRowActions 类型是 EmptyView 时才可用。本质上你是在对类型进行预先专门化。

如果你把这个新初始化器放在 MenuList 的主体中,你将会得到类似 Cannot convert value of type 'EmptyView' to closure result type 'AdditionalRowActions' 的错误,因为编译器不知道你希望 AdditionalRowActions 成为 EmptyView

struct MenuList<T: MenuListItem, AdditionalRowActions: View>: View
{
    private var additionalRowActions: (T, Binding<Bool>) -> AdditionalRowActions

    init(@ViewBuilder additionalRowActions: @escaping (T, Binding<Bool>) -> AdditionalRowActions)
    {
        self.additionalRowActions = additionalRowActions
    }
}

// New

extension MenuList where T == Void, AdditionalRowActions == EmptyView {
    init() {
        self.additionalRowActions = { (_, ) in EmptyView() }
    }
}
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章