问题复现
在Swift UI中,想要在body中输出“print(animationAmount)”,但是会存在下面的报错:
Type '()' cannot conform to 'View'
具体的代码如下:
import SwiftUI
struct ContentView: View {
@State private var animationAmount = 1.0
var body: some View {
print(animationAmount)
VStack {
Stepper("Scale amount", value: $animationAmount.animation(), in: 1...10)
Spacer()
Button("Tap Me") {
withAnimation {
animationAmount += 1
}
}
.padding(40)
.background(.red)
.foregroundStyle(.white)
.clipShape(.circle)
// .animation(.default, value: animationAmount)
.scaleEffect(animationAmount)
}
}
}
#Preview {
ContentView()
}
解决方案
不推荐的的解决方案为:
var body: some View {
print(animationAmount)
return VStack {
// 视图内容
}
}
推荐的解决方案:
var body: some View {
print(animationAmount)
VStack {
// 视图内容
Button("Tap Me") {
// 视图内容
print(animationAmount) // 在按钮的动作中打印
}
}
}
因此将两个解决方案拿出来,原因在于提供一个对比。print在body中输出报错的原因为,View的body部分是一个结构体属性,应该只负责描述视图的内容,而不应该提供其他的副作用。
我们的print在body中使用,会违反这一原则,也因此会产生编译器报错,提示你不应该在这里引入副作用(非视图的功能),所以,我们应该在按钮中使用print打印输出。
不推荐的解决方案中,print之所以可以工作,是因为Swift的类型推断机制,当我们在body中使用return时,Swift的类型推断机制会理解为这是一个明确的返回值,因此print才会工作,但它并不符合Swift UI声明式编程的设计理念。
还有一个不推荐的原因是,Swift UI视图的重建频率高,body会被频繁调用,当在body中放置副作用(print输出)时,会看到大量的冗余,甚至影响性能。
以上是本次的问题报错、分析和相关解决方案。