List 是常用的 SwiftUI 组件,在 iOS 中,其构造接口中的 selection 参数必须绑定到 Optional 型,否则 Swift Compiler 会报错。

尽管 SwiftUI 日渐成熟,但实际开发中可能还是会遇到一些莫名其妙的问题。糟糕的是,到 Xcode 16.2 为止,Swift Compiler 的报错提示有时候还是差点意思。比如有时候会报如下错误:

the compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions

第一次遇到这个问题很让人摸不着头脑。实际上,上述错误基本都是因为表达式中有类型相关的错误,但这个报错提示没有给出有价值的信息来帮助开发者定位具体的错误位置。

比如以下代码:

List(selection: $selection) 

当 selection 为非 Set 时(为 Set 时,List 在编辑模式下支持多选),必须定义为可选型,否则就会报上述错误。而且邪门的是,仅会在 iOS 上报错,macOS 上完全没问题。相关讨论:SwiftUI 4 List initializer not available in iOS.

同样的,在 onChange 方法中,根据监听值 selection 的类型,newValue 也要处理可选还是非可选,否则有时候编译器一样会稀里糊涂地报上述错误。

.onChange(of: selection, { oldValue, newValue in
	if let _ selection = selection {}
})

在回到 List(selection: $selection) ,还需要注意,这里的 selection 参数必须符合 Hashable 协议,这就导致如果尝试将 selection 绑定到一个协议上会报错。比如:

@Binding var selection: any MySelection

相关讨论可以参考这里:SwiftUI Binding problems with protocols.

这个特性在一些情况下会很好用,还是期待后续的 Swift 能支持这个特性。