1

我一遍又一遍地为此苦苦挣扎,所以我想我错过了一些东西。我需要进行数学运算、进行设置、分配值或任何一系列简单操作以响应某些用户操作,例如此处显示的示例,而 SwiftUI 想要一个我不需要视图的视图。必须有办法绕过 ViewBuilder 的规则。我通过创建一个不必要的视图并在视图的 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")
            }
        }
    }
}
4

4 回答 4

1
struct ExecuteCode : View {
    init( _ codeToExec: () -> () ) {
        codeToExec()
    }
    
    var body: some View {
        return EmptyView()
    }
}

用法:

HStack {
    ExecuteCode { print("SomeView1 was re-drawn!") }
    SomeView1()
}
于 2021-01-26T16:09:54.163 回答
0

你不能做你想做的事,因为实际上里面的每个视图块body都是一个ViewBuidler.buildBlock函数参数。IE。你在函数参数空间。我希望你不要期待这样的表达

foo(Toggle(), if showStuff { ... } )

会工作(假设foofunc foo(args: View...)。但这是你试图在body.

因此 SwiftUI 中的表达式必须在ViewBuilder块之外(ViewBuilder 本身支持视图的一些例外情况)。

这是您的情况的解决方案:

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 切换开关中查找

注意:(View.body不包括一些动作修饰符)等价于UIView.draw(_ rect:)...您不会将 UserDefaults 存储在 draw(_ rect:) 中,对吗?

于 2020-07-25T16:08:52.797 回答
0

在 SwiftUI 2.0 中,有一个新的 ViewModifier onChange(of:perform:),它允许您对值的变化做出反应。

但是你可以用一个巧妙的技巧来创建类似的东西(我忘了我在哪里看到它,所以很遗憾我不能留下正确的归属),通过扩展一个BindingwithonChange方法:

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
         })
   }
}

你可以像这样使用它:

Toggle(isOn: $showStuff.onChange(perform: { (new, old) in
  if new {
     UserDefaults.standard.set(true, forKey: "Something")
  }
}))
于 2020-07-25T17:38:31.723 回答
0

视图实际上是所谓的Function Builders,视图主体的内容用作函数的参数buildBlock,正如@Asperi 所提到的。

如果您必须在此上下文中运行代码,另一种解决方案是使用返回所需视图的闭包:

VStack {
    // ... some views ...
    { () -> Text in
      // ... any code ...
      return Text("some view") }()
    // ... some views ...
}
于 2021-10-18T21:53:43.233 回答