我一直在为此苦苦挣扎,所以我想我缺少了一些东西。我需要进行数学运算,进行设置,分配值或许多简单操作来响应某些用户操作,例如此处显示的示例,而SwiftUI则需要一个不需要视图的View。必须有一种方法来绕过ViewBuilder的规则。我通过创建一个不必要的视图并在View的init()中执行所需的代码来解决此问题,但这似乎很尴尬。
import SwiftUI
struct ContentView: View
{
@State var showStuff = false
var body: some View
{
VStack
{
Toggle(isOn: $showStuff)
{
Text("Label")
}
if showStuff
{
UserDefaults.standard.set(true, forKey: "Something")
}
}
}
}
答案 0 :(得分:0)
您无法做您想做的事情,因为实际上body
内的每个视图块都是一个ViewBuidler.buildBlock
函数参数。就是您在函数参数空间中。希望您不要期望像这样的表情
foo(Toggle(), if showStuff { ... } )
会工作(假设foo
是func foo(args: View...)
。但这就是您在body
中尝试做的事情。
因此,SwiftUI中的表达式必须
以下是您的解决方案:
SwiftUI 2.0
struct ContentView: View {
@AppStorage("Something") var showStuff = false
var body: some View {
VStack {
Toggle(isOn: $showStuff) {
Text("Label")
}
}
}
}
SwiftUI 1.0
查找已经解决的SwiftUI toggle switches
注意:View.body
(不包括某些动作修饰符)等效于UIView.draw(_ rect:)
...您不将UserDefaults存储在draw(_ rect :)中,对吗?
答案 1 :(得分:0)
在SwiftUI 2.0中,有一个新的ViewModifier onChange(of:perform:)
,可让您对值的更改做出反应。
但是,您可以通过使用X1 <- gsub('<br/>', '\n', X)
xTabs <- XML::readHTMLTable(X1)
方法扩展Binding
来创建与之类似的巧妙技巧(我忘了看到它的地方,所以很遗憾我无法留下适当的归属):
onChange
您可以像这样使用它:
extension Binding {
func onChange(perform action: @escaping (Value, Value) -> Void) -> Self {
.init(
get: { self.wrappedValue },
set: { newValue in
let oldValue = self.wrappedValue
DispatchQueue.main.async { action(newValue, oldValue) }
self.wrappedValue = newValue
})
}
}
答案 2 :(得分:0)
struct ExecuteCode : View {
init( _ codeToExec: () -> () ) {
codeToExec()
}
var body: some View {
return EmptyView()
}
}
用法:
HStack{
SomeView1()
Spacer()
ExecuteCode { print("SomeView1 was re-drawn!") }
}