SwiftUI发送按钮点击到子视图

Jos*_*osh 1 ios swift swiftui

我有几个视图包含具有一些不同内容的相同按钮。因此,我制作了一个ContainerView包含共享Button布局的文件,并为通用ContentView.

我希望在点击按钮ContentView时做出响应ContainerView

使用 UIKit,我将持有对ContentViewin 的引用,并在ContainerView按下按钮时调用它的函数。但是,因为 SwiftUI 将所有视图都作为结构体,所以contentView在放入ContainerViewbody. 因此参考和显示ContentView是不同的,我无法向子视图发送消息。

代码:

struct ContainerView: View {
    let contentView = ContentView()

    var body: some View {
        Group {
            /// When this button is tapped, I would like to send a message to the `ContentView`.
            Button(action: self.reset, label: { Text("RESET") })
            /// Unfortunately, this seemes to send a copy of the `contentView`. So I am unable to send the
            /// corrent struct a message.
            ///
            /// How can I send a subview a message from the superview?
            self.contentView
        }
    }

    func reset() {
        self.contentView.reset()
    }
}

struct ContentView: View {
    @State private var count: Int = 0

    var body: some View {
        Group {
            Text("Count: \(self.count)")
            Button(action: self.increment, label: { Text("Increment") })
        }
    }

    func increment() {
        self.count += 1
    }

    /// When this is called from the `ContainerView`, it is accessing a different ContentView 
    /// struct than is being displayed.
    func reset() {
        self.count = 0
    }
}
Run Code Online (Sandbox Code Playgroud)

所以问题是:ContentView当点击 中的按钮时,如何向其中发送消息并运行一些代码ContainerView

Jos*_*ach 5

与其尝试存储对子视图的引用,为什么不在它们之间进行绑定?在您的示例中,这可能是通过绑定到计数。

struct ContainerView: View {
    @State private var count = 0

    var body: some View {
        // Your Button wrapping the ContentView
        ContentView(count: $count)
    }

    func reset() {
        self.count = 0
    }
}


struct ContentView: View {
    @Binding var count: Int

    // ContentView's body
}
Run Code Online (Sandbox Code Playgroud)

ContainerView重置计数时,绑定将更新孩子。

编辑:我看到您关于想要ContentView控制重置逻辑的评论。如何尝试复制某些功能,例如NavigationLinkisActive:系统在导航中设置布尔值,然后重置?

在您的情况下,您可以尝试以下操作:

struct ContainerView: View {
    @State private var shouldReset: Bool = false

    var body: some View {
        // Your Button wrapping the ContentView
        ContentView(shouldReset: $shouldReset)
    }

    func reset() {
        self.shouldReset = true
    }
}


struct ContentView: View {
    @Binding var shouldReset: Bool {
        didSet {
            if shouldReset {
                // Call your reset logic here
            }
            shouldReset = false
        }
    }

    // ContentView's body
}
Run Code Online (Sandbox Code Playgroud)

ContentView会知道更改,我们会将其视为单独的“状态”,然后一旦操作完成,该状态就会重置。

这可能不是理想的解决方案,但对我来说,它似乎复制了一些第一方 SwiftUI 组件显示的模式。