如何在 SwiftUI 视图中执行非视图代码

Rus*_*uss 11 swiftui viewbuilder

我一次又一次地为此苦苦挣扎,所以我想我错过了一些东西。我需要做数学、进行设置、分配值或任何一系列简单操作来响应某些用户操作,例如此处显示的示例,而 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")
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

And*_*rew 17

方式1(最好):

struct ExecuteCode : View {
    init( _ codeToExec: () -> () ) {
        codeToExec()
    }
    
    var body: some View {
        EmptyView()
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

HStack {
    ExecuteCode { 
        print("SomeView1 was re-drawn!")
        print("second print")
    }

    SomeView1()
}
Run Code Online (Sandbox Code Playgroud)

方式二:

(我的第一种方法更好 - 你只能在这里编写简单的代码)

HStack {
    // `let _ =` works inside of View!
    let _ = print("SomeView1 was re-drawn!") 

    SomeView1()
}
Run Code Online (Sandbox Code Playgroud)

方式三:

(+- 与第一种方式相同的情况。足够好的解决方案。)

HStack {
    let _ = { // look here. "let _ =" is required
        print("SomeView1 was re-drawn!")
        print("second print")
    }() // look here. "()" is also required
    
    SomeView1()
}
Run Code Online (Sandbox Code Playgroud)


Sid*_*pta 0

我认为现在最好的方法是使用onChange(of:perform:)修饰符,适用于 iOS14.0+

这些简单的执行(比如做数学、赋值)只不过是swift 术语中的操作,应该在触摸任何 UI 元素后执行,因为 swiftUI 是声明性的。就您而言,您可以将其与任何视图类型一起使用。其他类似的选项是.onAppear().onDisappear()(不言自明)。

令人惊讶的是,苹果的这些文档实际上非常好且详尽。

链接 - https://developer.apple.com/documentation/swiftui/view/onchange(of:perform:)