在@ViewBuilder 闭包中更改@State
Change @State in a @ViewBuilder closure
我正在尝试了解如何在 @ViewBuilder
闭包中更改 @State
变量。以下只是一个简单的例子:
struct ContentView: View {
@State var width = CGFloat(0)
var body: some View { //Error 1
GeometryReader { geometry in //Error 2
self.width = geometry.size.width
return Text("Hello world!")
}
}
}
我遇到了一些错误:
错误 1:
Function declares an opaque return type, but has no return statements
in its body from which to infer an underlying type
但是 return
是多余的,因为 View
中只有一行代码计算 属性。
错误 2:
Cannot convert return expression of type 'GeometryReader<_>' to return
type 'some View'
既然我明确写了return Text("...")
类型不应该清楚吗?
这里有什么问题?
首先,您不能在 functionBuilder
中任意 swift 陈述。允许使用特定语法。在 SwiftUI 的情况下,它是一个 ViewBuilder
,它在幕后构成您的类型。当您在 SwiftUI 中进行连续语句时,您实际上是在依赖编译器根据该 DSL 的规则在其下组合一个新类型。
2、SwiftUI是配方,不是事件系统。您 不 更改 body
函数中的状态变量,您设置当状态变量在外部发生变化时事物应该如何反应。如果您希望另一个视图以某种方式对该宽度做出反应,则需要根据您想要的组件的宽度来定义该内容。在不知道您的最终目标是什么的情况下,很难回答如何将内容相互联系起来。
编辑:
我被要求详细说明究竟允许什么。每个 functionBuilder
都有不同的允许语法,这些语法在 functionBuilder
本身中定义。这对 Swift 5.1 中的函数构建器有很好的概述:https://www.swiftbysundell.com/posts/the-swift-51-features-that-power-swiftuis-api
至于SwiftUI具体找的是什么,本质上就是找return一个View
.
实例的每个语句
// works fine!
VStack {
Text("Does this")
Text("Work?")
}
// doesn't work!
VStack {
Text("Updating work status...")
self.workStatus = .ok // this doesn't return an instance of `View`!
}
// roundabout, but ok...
VStack {
Text("Being clever")
gimmeView()
}
// fine to execute arbitrary code now, as long as we return a `View`
private func gimmeView() -> some View {
self.workingStatus = .roundabout
return Text("Yes, but it does work.")
}
这就是为什么您会遇到钝错误的原因:
Cannot convert return expression of type 'GeometryReader<_>' to return type 'some View'
类型系统无法从 View
中构造出任何 View
,并且在您执行时基本上 Void
:
self.width = geometry.size.width
当你执行连续的 View
语句时,在下面,它仍然被转换成一种新的类型 View
:
// the result of this is TupleView<Text, Text>
Text("left")
Text("right")
我正在尝试了解如何在 @ViewBuilder
闭包中更改 @State
变量。以下只是一个简单的例子:
struct ContentView: View {
@State var width = CGFloat(0)
var body: some View { //Error 1
GeometryReader { geometry in //Error 2
self.width = geometry.size.width
return Text("Hello world!")
}
}
}
我遇到了一些错误:
错误 1:
Function declares an opaque return type, but has no return statements in its body from which to infer an underlying type
但是 return
是多余的,因为 View
中只有一行代码计算 属性。
错误 2:
Cannot convert return expression of type 'GeometryReader<_>' to return type 'some View'
既然我明确写了return Text("...")
类型不应该清楚吗?
这里有什么问题?
首先,您不能在 functionBuilder
中任意 swift 陈述。允许使用特定语法。在 SwiftUI 的情况下,它是一个 ViewBuilder
,它在幕后构成您的类型。当您在 SwiftUI 中进行连续语句时,您实际上是在依赖编译器根据该 DSL 的规则在其下组合一个新类型。
2、SwiftUI是配方,不是事件系统。您 不 更改 body
函数中的状态变量,您设置当状态变量在外部发生变化时事物应该如何反应。如果您希望另一个视图以某种方式对该宽度做出反应,则需要根据您想要的组件的宽度来定义该内容。在不知道您的最终目标是什么的情况下,很难回答如何将内容相互联系起来。
编辑:
我被要求详细说明究竟允许什么。每个 functionBuilder
都有不同的允许语法,这些语法在 functionBuilder
本身中定义。这对 Swift 5.1 中的函数构建器有很好的概述:https://www.swiftbysundell.com/posts/the-swift-51-features-that-power-swiftuis-api
至于SwiftUI具体找的是什么,本质上就是找return一个View
.
// works fine!
VStack {
Text("Does this")
Text("Work?")
}
// doesn't work!
VStack {
Text("Updating work status...")
self.workStatus = .ok // this doesn't return an instance of `View`!
}
// roundabout, but ok...
VStack {
Text("Being clever")
gimmeView()
}
// fine to execute arbitrary code now, as long as we return a `View`
private func gimmeView() -> some View {
self.workingStatus = .roundabout
return Text("Yes, but it does work.")
}
这就是为什么您会遇到钝错误的原因:
Cannot convert return expression of type 'GeometryReader<_>' to return type 'some View'
类型系统无法从 View
中构造出任何 View
,并且在您执行时基本上 Void
:
self.width = geometry.size.width
当你执行连续的 View
语句时,在下面,它仍然被转换成一种新的类型 View
:
// the result of this is TupleView<Text, Text>
Text("left")
Text("right")