Hi there, I cannot find a solution to create a wrapper menu view. What I try here is to conform to a protocol to have a list of actions but it seems the actions cannot modify wrapped view state. Is it possible to do this? Thanks
struct MenuItem: Identifiable {
var id: String { title }
var title: String
var action: () -> Void
}
protocol Menu {
var menuItems: [MenuItem] { get }
}
import SwiftUI
struct ValueView: View, Menu {
@State private var value = 1
var body: some View {
HStack {
Text("Value: \(value)")
.font(.title)
Button("ADD INSIDE VIEW", action: add)
// It works right
// When printing self _location is not NIL
}
}
private func add() {
print("Value before: \(value)")
value += 1
print("Value after: \(value)")
print(self)
}
var menuItems: [MenuItem] {
[MenuItem(title: "Add", action: add)]
// It doesn't work
// When printing self _location is NIL
}
}
import SwiftUI
struct MenuView<Content>: View where Content: View & Menu {
var content: () -> Content
init(@ViewBuilder content: @escaping () -> Content) {
self.content = content
}
var body: some View {
VStack {
content()
ForEach(content().menuItems) { item in
Button(item.title, action: item.action)
.font(.headline)
.padding()
}
Spacer()
}
}
}
import SwiftUI
@main struct MyApp: App {
var body: some Scene {
WindowGroup {
MenuView {
ValueView()
}
}
}
}
/* Result when printing from ADD INSIDE VIEW */
Value before: 1
Value after: 2
ValueView(_value: SwiftUI.State<Swift.Int>(_value: 1, _location: Optional(SwiftUI.StoredLocation<Swift.Int>)))
/* Result when printing from dynamically generated button */
Value before: 1
Value after: 1
ValueView(_value: SwiftUI.State<Swift.Int>(_value: 1, _location: nil))