我试图了解如何更改闭包中的@State
变量@ViewBuilder
。以下只是一个简单的示例:
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:
函数声明了一个不透明的返回类型,但是在其主体中没有用于从其推断基础类型的返回语句
但这return
是多余的,因为在View
计算属性内只有一行代码。
错误2:
无法将类型'GeometryReader <_>'的返回表达式转换为返回类型'some View'
既然我明确地写return Text("...")
了,那类型就不应该清楚吗?
这是什么问题
首先,您不能在中做出任意的swift语句functionBuilder
。允许使用特定的语法。在SwiftUI的情况下,它是一个ViewBuilder
,它在幕后构成您的类型。当您在SwiftUI中创建连续的语句时,实际上是在依赖编译器根据该DSL的规则在其下编写新类型。
第二,SwiftUI是一个配方,不是事件系统。您无需在body
函数中更改状态变量,而是可以设置状态变量在外部更改时应如何反应。如果希望另一个视图对该宽度做出某种反应,则需要根据所需组件的宽度定义该内容。不知道您的最终目标是什么,很难回答如何将内容相互关联。
编辑:
我被要求详细说明允许的内容。每个functionBuilder
都有其functionBuilder
自身定义的不同允许语法。这对Swift 5.1中的函数构建器有很好的概述:https : //www.swiftbysundell.com/posts/the-swift-51-features-that-power-swiftuis-api
至于SwiftUI专门寻找的东西,它实际上是在寻找每个语句以返回的实例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.") }
这就是为什么出现钝性错误的原因:
无法将类型'GeometryReader <_>'的返回表达式转换为返回类型'some View'
该类型的系统不能建立任何View
出来的View
,基本上Void
当你执行:
self.width = geometry.size.width
当您View
在下面执行连续语句时,它仍将被转换为一种新的类型View
:
// the result of this is TupleViewText("left") Text("right")