问题描述
在传递闭包视图时,发现传递闭包的代码报错。
ContentView视图中,在传递CardView视图闭包时,提示报错。
报错代码为:
CardView(card: cards[index]) {
withAnimation {
removeCard(at: index)
}
}
报错内容为:
Extra trailing closure passed in call
在CardView视图中,实际上是有闭包属性的:
struct CardView: View {
@State private var isShowingAnswer = false
@State private var offset = CGSize.zero
var removal: (() -> Void)? = nil
let card: Card
var body: some View {
...
}
}
排查和解决
起初以为是闭包在ContentView的环境内,因为某些原因导致无法解决。
然后改为手动包裹CardView的removal闭包:
CardView(card: cards[index], removal: {
withAnimation {
removeCard(at: index)
}
})
修改后仍然报错,报错代码为:
Argument 'removal' must precede argument 'card'
Replace 'card: cards[index], removal: {
withAnimation {
removeCard(at: index)
}
}' with 'removal: {
withAnimation {
removeCard(at: index)
}
}, card: cards[index]'
这个报错表示参数“removal”必须位于参数“card”之前。这时我就知道尾随闭包不能正常使用的原因为,闭包参数在CardView视图中,应该在最后一位。
因此,解决方案为,保持ContentView中的CardView代码不动:
CardView(card: cards[index]) {
withAnimation {
removeCard(at: index)
}
}
将CardView视图中的闭包参数removal调到最后的位置。
重新运行后,问题得到解决。
结论为:在 Swift 中,尾随闭包(trailing closure)的确要求闭包类型的参数位于方法或初始化器的最后一个位置。这是 Swift 的语法规则,因为尾随闭包的设计是为了简化代码语法,让闭包的使用更加直观。