Is there a way to pass mutating closures as arguments to a SwiftUI View? - swift

The Idea
In one of the views of my application I need to mutate some data. To make the code clear, testable and just to test how far I can get without logic in ViewModels, I've moved the mutating logic to the Model layer.
Say this is my Model
struct Model {
var examples: [Example] = []
/* lots of other irrelevant properties and a constructor here */
}
struct Example: Identifiable {
var id = UUID()
var isEnabled: Bool = true
/* other irrelevant properties and a constructor here */
}
And the function that mutates stuff is
// MARK: mutating methods
extension Model {
mutating func disableExamples(with ids: Set<UUID>) {
// do whatever, does not matter now
}
mutating func enableExamples(with ids: Set<UUID>) {
// do whatever, does not matter now
}
}
Now, let's display it in views, shall we?
struct ContentView: View {
#State private var model = Model()
var body: some View {
VStack {
Text("That's the main view.")
// simplified: no navigation/sheets/whatever
ExampleMutatingView(examples: $model.examples)
}
}
}
struct ExampleMutatingView: View {
#Binding var examples: [Example]
var body: some View {
VStack {
Text("Here you mutate the examples.")
List($examples) {
// TODO: do stuff
}
}
}
}
The attempt
Since I don't want to put the whole Model into the ExampleMutatingView, both because I don't need the whole thing and due to performance reasons, I tried to supply the view with necessary methods.
I've also added the ability to select examples by providing a State variable.
struct ContentView: View {
#State private var model = Model()
var body: some View {
VStack {
Text("That's the main view.")
// simplified: no navigation/sheets/whatever
ExampleMutatingView(examples: $model.examples,
operationsOnExamples: (enable: model.enableExamples, disable: model.disableExamples))
}
}
}
struct ExampleMutatingView: View {
#Binding var examples: [Example]
let operationsOnExamples: (enable: ((Set<UUID>) -> Void, disable: (Set<UUID>) -> Void)
#State private var multiSelection = Set<UUID>()
var body: some View {
VStack {
Text("Here you mutate the examples.")
List($examples, selection: $multiSelection) { example in
Text("\(example.id)")
}
HStack {
Button { operationsOnExamples.enable(with: multiSelection) } label: { Text("Enable selected") }
Button { operationsOnExamples.disable(with: multiSelection) } label: { Text("Disable selected") }
}
}
}
}
The problem
The thing is, with such setup the ContentView greets me with Cannot reference 'mutating' method as function value error. Not good, but mysterious for me for the very reason that fixes it: supplying the actual Model into the view.
The (non ideal) solution
Showing only the parts that changed
// ContentView
1. ExampleMutatingView(model: $model)
// ExampleMutatingView
1. #Binding var model: Model
2. List($model.examples/*...*/)
3. Button { model.enableExamples(with: multiSelection) } /*...*/
4. Button { model.disableExamples(with: multiSelection) } /*...*/
The discussion
Why is it the case? The only difference I see and cannot explain accurately between these two is that supplying the model might give the method access to its self, which is, otherwise, not available. If that's the case, maybe wrapping the methods in some kind of closure with an [unowned self] would help?
I'm fresh to the topic of self in Swift, so I honestly have no idea.
TL;DR: why does it work when I supply the object defining the methods, but does not when I supply only the methods?

Related

How can I call a function of a child view from the parent view in swiftUI to change a #state variable?

I'm trying to get into swift/swiftui but I'm really struggling with this one:
I have a MainView containing a ChildView. The ChildView has a function update to fetch the data to display from an external source and assign it to a #State data variable.
I'd like to be able to trigger update from MainView in order to update data.
I've experienced that update is in fact called, however, data is reset to the initial value upon this call.
The summary of what I have:
struct ChildView: View {
#State var data: Int = 0
var body: some View {
Text("\(data)")
Button(action: update) {
Text("update") // works as expected
}
}
func update() {
// fetch data from external source
data = 42
}
}
struct MainView: View {
var child = ChildView()
var body: some View {
VStack {
child
Button(action: {
child.update()
}) {
Text("update") // In fact calls the function, but doesn't set the data variable to the new value
}
}
}
}
When googling for a solution, I only came across people suggesting to move update and data to MainView and then pass a binding of data to ChildView.
However, following this logic I'd have to blow up MainView by adding all the data access logic in there. My point of having ChildView at all is to break up code into smaller chunks and to reuse ChildView including the data access methods in other parent views, too.
I just cannot believe there's no way of doing this in SwiftUI.
Is completely understandable to be confused at first with how to deal with state on SwiftUI, but hang on there, you will find your way soon enough.
What you want to do can be achieved in many different ways, depending on the requirements and limitations of your project.
I will mention a few options, but I'm sure there are more, and all of them have pros and cons, but hopefully one can suit your needs.
Binding
Probably the easiest would be to use a #Binding, here a good tutorial/explanation of it.
An example would be to have data declared on your MainView and pass it as a #Binding to your ChildView. When you need to change the data, you change it directly on the MainView and will be reflected on both.
This solutions leads to having the logic on both parts, probably not ideal, but is up to what you need.
Also notice how the initialiser for ChildView is directly on the body of MainView now.
Example
struct ChildView: View {
#Binding var data: Int
var body: some View {
Text("\(data)")
Button(action: update) {
Text("update") // works as expected
}
}
func update() {
// fetch data from external source
data = 42
}
}
struct MainView: View {
#State var data: Int = 0
var body: some View {
VStack {
ChildView(data: $data)
Button(action: {
data = 42
}) {
Text("update") // In fact calls the function, but doesn't set the data variable to the new value
}
}
}
}
ObservableObject
Another alternative would be to remove state and logic from your views, using an ObservableObject, here an explanation of it.
Example
class ViewModel: ObservableObject {
#Published var data: Int = 0
func update() {
// fetch data from external source
data = 42
}
}
struct ChildView: View {
#ObservedObject var viewModel: ViewModel
var body: some View {
Text("\(viewModel.data)")
Button(action: viewModel.update) {
Text("update") // works as expected
}
}
}
struct MainView: View {
#StateObject var viewModel = ViewModel()
var body: some View {
VStack {
ChildView(viewModel: viewModel)
Button(action: {
viewModel.update()
}) {
Text("update") // In fact calls the function, but doesn't set the data variable to the new value
}
}
}
}

MVVM model in SwiftUI

I want to separate view from view model according to MVVM. How would I create a model in SwiftUI? I read that one should use struct rather than class.
As an example I have a model for a park where you can plant trees in:
// View Model
struct Park {
var numberOfTrees = 0
func plantTree() {
numberOfTrees += 1 // Cannot assign to property: 'self' is immutable
}
}
// View
struct ParkView: View {
var park: Park
var body: some View {
// …
}
}
Read things about #State in such things, that make structs somewhat mutable, so I tried:
struct Park {
#State var numberOfTrees = 0 // Enum 'State' cannot be used as an attribute
func plantTree() {
numberOfTrees += 1 // Cannot assign to property: 'self' is immutable
}
}
I did use #State successfully directly in a View. This doesn’t help with separating the view model code though.
I could use class:
class Park: ObservableObject {
var numberOfTrees = 0
func plantTree() {
numberOfTrees += 1
}
}
…but then I would have trouble using this view model nested in another one, say City:
struct City {
#ObservedObject var centerPark: Park
}
Changes in centerPark wouldn’t be published as Park now is reference type (at least not in my tests or here). Also, I would like to know how you solve this using a struct.
as a starting point:
// Model
struct Park {
var numberOfTrees = 0
mutating func plantTree() { // `mutating`gets rid of your error
numberOfTrees += 1
}
}
// View Model
class CityVM: ObservableObject {
#Published var park = Park() // creates a Park and publishes it to the views
// ... other #Published things ...
// Intents:
func plantTree() {
park.plantTree()
}
}
// View
struct ParkView: View {
// create the ViewModel, which creates the model(s)
// usually you would do this in the App struct and make available to all views by .environmentObject
#StateObject var city = CityVM()
var body: some View {
VStack {
Text("My city has \(city.park.numberOfTrees) trees.")
Button("Plant one more") {
city.plantTree()
}
}
}
}
mutating func is the fix but I thought I'd include some other info below:
We don't use MVVM with SwiftUI because we don't use classes for transient view state and we don't control the View in the MVVM/MVC sense. SwiftUI creates and updates the real view objects automatically for us, i.e. UILabels, UITableView etc. The SwiftUI View structs are essentially the view model already, so if you were to recreate that as an object not only will you be needlessly make your code more complex but also would introduce object reference bugs SwiftUI is trying to eliminate by using structs. With property wrappers like #State and #Binding SwiftUI is doing some magic to make the struct behave like an object it is not a good idea to ignore that. To make your View structs more testable you can extract related vars into a struct and use mutating funcs like this:
// View Model
struct ParkConfig {
var numberOfTrees = 0
mutating func plantTree() {
numberOfTrees += 1
}
}
struct ContentView {
#State var parkConfig = ParkConfig()
var body: some View {
ParkView(config: $parkConfig)
}
}
// View
struct ParkView: View {
#Binding var config: ParkConfig
var body: some View {
Button("Click Me") {
config.plantTree()
}
}
}
You can see Apple demonstrate this pattern in Data Essentials in SwiftUI WWDC 2020 at 4:18 where he says "EditorConfig can maintain invariants on its properties and be tested independently. And because EditorConfig is a value type, any change to a property of EditorConfig, like its progress, is visible as a change to EditorConfig itself."

Keeping data in SwiftUI MVVM hierarchy without persistence

I am new to SwiftUI, coming from Java. I know MVC pattern and try to understand MVVM in SwiftUI. It kindly works, but I don't know how to keep data between View hierarchy... also the View should not know anything about models, so I tried using the ViewModels passing around the views. Each ViewModel than should manage their Model.
First Question: Is this a good way to implement MVVM in SwiftUI like I did?
Second: Anyone here who could help me out to divide strictly Model from View and getting this code working?
For now I can add a Garage, go into GarageView and add certain Car models. After switching back to GarageListView and adding another Garage model all Car models from first Garage model are gone... what am I doing wrong? ;(
import SwiftUI
// Models
struct Car: Identifiable, Codable {
var id = UUID()
var name: String
}
struct Garage: Identifiable, Codable {
var id = UUID()
var name: String
var cars: [Car] = []
}
// ViewModels
class GarageListViewModel: ObservableObject {
#Published var garages: [Garage] = []
}
class GarageViewModel: ObservableObject {
#Published var garage: Garage
init(garage: Garage) {
self.garage = garage
}
}
class CarViewModel: ObservableObject {
#Published var car: Car
init(car: Car) {
self.car = car
}
}
// Views
struct GarageListView: View {
#ObservedObject var viewModel: GarageListViewModel
var body: some View {
List {
ForEach(viewModel.garages) { garage in
NavigationLink {
GarageView(viewModel: GarageViewModel(garage: garage))
} label: {
Text(garage.name)
}
}
}
.toolbar {
Button {
viewModel.garages.append(Garage(name: "My Garage"))
} label: {
Label("Add", systemImage: "plus")
}
}
}
}
struct GarageView: View {
#ObservedObject var viewModel: GarageViewModel
var body: some View {
List {
ForEach(viewModel.garage.cars) { car in
NavigationLink {
CarDetailView(viewModel: CarViewModel(car: car))
} label: {
Text(car.name)
}
}
}
.toolbar {
Button {
viewModel.garage.cars.append(Car(name: "My Car"))
} label: {
Label("Add", systemImage: "plus")
}
}
}
}
struct CarDetailView: View {
#ObservedObject var viewModel: CarViewModel
var body: some View {
Text(viewModel.car.name)
}
}
struct ContentView: View {
#StateObject var viewModel = GarageListViewModel()
var body: some View {
NavigationView {
GarageListView(viewModel: viewModel)
}
}
}
I would switch from using struct to class. Structs are passed by value, so you'd never get the exact same struct but a copy of it. By adding a new GarageViewModel, SwiftUI will rerender the List, that's why you lose your garages' cars when you add a new garage.
On a side note, you also forgot to add a NavigationView around your GarageListView and the List in the GarageView, rendering the NavigationLinks useless.
It can be a bit overwhelming to get into MVVC. I would definitely go through Apple's SwiftUI Tutorials as they subtly go through how to set up an MVVC.
As #loremipsum said, you should never init your ViewModel in a view struct because structs are immutable value types, and SwiftUI simply discards the view and recreates it, recreating EVERYTHING inside of it. Also, as you said yourself, your views shouldn't know about the inner workings of the model, so the model should change itself. Therefore, adding garages and cars should be handled in the ViewModel.
Another thing with the ViewModel; you do not need one for EACH view. In this case, one GaragesViewModel can handle all your data. And it should. Apple talks about having a "single source of truth'. That means that there is ONE place your views can go and get the data. That is your ViewModel. Unless you have a wholly unrelated set of data, keep it in one model.
Lastly, before some example code, not every view needs to have the model, or even a mutable parameter. Remember, views are disposable, and with them their parameters are disposed of. If you mutate the model, you will get a new view, so let constants are fine to use. I left your models alone and removed the CarViewModel. It is not needed in this example.
// ViewModel
class GaragesViewModel: ObservableObject {
// This initializes the model IN the model and provides a Singleton.
// You can refer to it anywhere you need to in code.
static var shared = GaragesViewModel()
#Published var garages: [Garage] = []
// Data manipulation in the model
public func addNewGarage() {
garages.append(Garage(name: "My Garage"))
}
public func add(car: Car, to garage:Garage) {
// The guard will stop the func if garage is not in garages.
guard let index = garages.firstIndex(where: { $0.id == garage.id }) else { return }
garages[index].cars.append(car)
}
}
// Views
struct ContentView: View {
var body: some View {
NavigationView {
GarageListView()
}
}
}
struct GarageListView: View {
// Since this is the only view that needs the model, it is called here.
// There is no need to pass it in.
#ObservedObject var viewModel = GaragesViewModel.shared
var body: some View {
List {
ForEach(viewModel.garages) { garage in
NavigationLink {
GarageView(garage: garage)
} label: {
Text(garage.name)
}
}
}
.toolbar {
Button {
GaragesViewModel.shared.addNewGarage()
} label: {
Label("Add", systemImage: "plus")
}
}
}
}
struct GarageView: View {
// GarageView doesn't mutate garage, so it can be a let constant. KISS principal.
let garage: Garage
var body: some View {
List {
ForEach(garage.cars) { car in
NavigationLink {
CarDetailView(car: car)
} label: {
Text(car.name)
}
}
}
.toolbar {
Button {
// if you wanted, you could add a func to car to return a new "My Car"
// and further separate the model.
GaragesViewModel.shared.add(car: Car(name: "My Car"), to: garage)
} label: {
Label("Add", systemImage: "plus")
}
}
}
}
struct CarDetailView: View {
// CarDetailView doesn't mutate car, so it can be a let constant.
let car: Car
var body: some View {
Text(car.name)
}
}
Welcome to StackOverflow! You just got yourself too far into the weeds trying to implement this, but it was a good first shot.
edit:
You can add something like:
public func changeName(of car: Car, in garage: Garage, to name: String) {
guard let garageIndex = garages.firstIndex(where: { $0.id == garage.id }),
let carIndex = garage.cars.firstIndex(where: { $0.id == car.id }) else { return }
garages[garageIndex].cars[carIndex].name = name
}
to your model, and then use it like this:
struct CarDetailView: View {
// Make car an #State variable so you can change it, and then pass the change to the func in the model.
#State var car: Car
let garage: Garage
var body: some View {
VStack {
TextField("", text: $car.name)
.padding()
Button {
GaragesViewModel.shared.changeName(of: car, in: garage)
} label: {
Text("Save")
}
}
}
}
Now, this is for learning purposes only. I would not use this in a shipping app as you have no persistence of your data. If you need to create a database of cars and garages, etc. I would use CoreData to track it, and it works a little differently than just using the structs and class we have here.
Also, if you have any more questions, you really need to make a new question. The purpose of StackOverflow is to get discrete answers to discrete questions, and so follow on questions are discouraged.

Swift - How to pass Binding values through View hierarchies?

I'm a week in to learning Swift and I'm using SwiftUI to create Views and MVVM to pass data to those views. However because I'm use to React Native in JavaScript I'm a little confused on how to pass data & binding values ("state") in the SwiftUI World
In React Native we have
() -> {
const state = { /* some state */ }
// state logic happens in this parent
(state) -> {
(state) -> ...
(state) -> ...
(state) -> ...
}
(state) -> {
(state) -> ...
(state) -> ...
(state) -> ...
}
}
And so on. So each child has access to the parent state as we pass it down
The idea in React is we have the parent component that holds and manages the state. You can construct complex views/components by putting simpler components together making a hierarchy. But it's the parent or the start of that hierarchy thats the container for that complex view/component which handles the logic of the state.
I tried to follow this same pattern in SwiftUI but instantly ran into problems.
If we had three Views in SwiftUI:
// Bottom of hierarchy
struct NumberView: View {
var body: some View {
VStack {
Text("\($number)")
Button("ADD", action: { $number += 1 })
}
}
var number: Binding<Int>
}
// Middle of hierarchy
struct TextViewWithNumber: View {
var body: some View {
VStack {
Text(someText)
NumberView(number: $number)
}
}
var someText: String
var number: Binding<Int>
}
// Top of hierarchy
struct ContentView: View {
#ObservedObject var viewModel = ViewModel()
var body: some View {
VStack {
TextViewWithNumber(someText: viewModel.string1, number: $viewModel.number1)
TextViewWithNumber(someText: viewModel.string2, number: $viewModel.number2)
}
}
}
struct Model {
var string1: String
var string2: String
var number1: Int
var number2: Int
init() {
string1 = "It's not a motorcycle, baby It's a chopper"
string2 = "Zed's dead"
number1 = 5
number2 = 10
}
}
class ViewModel: ObservableObject {
#Published private var viewModel = Model()
// MARK: - Access to the model
var viewModel: Model {
viewModel
}
// MARK: - Intent(s)
func updateModel() {
// Model Update Code
}
I got a bunch of errors like viewModel is get only and value type Binding<T> is not of type Binding<T>.Wrapper and is was basically going in circles at this point.
So, how should you pass ObservableObjects & Bindings in a View hierarchy in SwiftUI?
Similar to passing "state" and "props" in React (if you're familiar with react).
I'm looking for the right way to do this so if whole comparing it to React idea is wrong ignore my comparison.
SwiftUI and ReactNative are similar, up to a certain point. ReactNative is using the Redux pattern, while SwiftUI, ergh.., allows some nasty shortcuts that iOS developers are kinda "loving" them (#EnvironmentObject being one of them).
But enough blabbing around, you do have some mistakes in your code that prevent you from using your views as you'd want.
Firstly, there are some incorrect usages of bindings, you should be #Binding var someValue: SomeType instead of var someValue: Binding<SomeType, as the compiler provides the $ syntax only for property wrappers (#Binding is a property wrapper).
Secondly, once you have bindified everything you need (the number property in your case, you no longer need to reference the properties via $ when reading/writing to them, unless you want to forward them as bindings. Thus, write Text("\(number)"), and Button("ADD", action: { number += 1 }).
Thirdly, the #Published variable needs to be public, and be directly referenced. I assume you attempted some encapsulation there with the computed property, however this will simply not work with SwiftUI - bindings require a two-way street so that the changes can easily propagate. If you want to keep your view model in sync with the changes of the model property, then you can add a didSet on that property and do whatever stuff you need to do when the model data changes.
With the above in mind, your code could look something like this:
// Bottom of hierarchy
struct NumberView: View {
var body: some View {
VStack {
Text("\(number)")
Button("ADD", action: { number += 1 })
}
}
#Binding var number: Int
}
// Middle of hierarchy
struct TextViewWithNumber: View {
var body: some View {
VStack {
Text(someText)
NumberView(number: $number)
}
}
var someText: String
#Binding var number: Int
}
// Top of hierarchy
struct ContentView: View {
#ObservedObject var viewModel = ViewModel()
var body: some View {
VStack {
TextViewWithNumber(someText: viewModel.model.string1, number: $viewModel.model.number1)
TextViewWithNumber(someText: viewModel.model.string2, number: $viewModel.model.number2)
}
}
}
struct Model {
var string1: String
var string2: String
var number1: Int
var number2: Int
init() {
string1 = "It's not a motorcycle, baby It's a chopper"
string2 = "Zed's dead"
number1 = 5
number2 = 10
}
}
class ViewModel: ObservableObject {
#Published var model = Model() {
didSet {
// react to descendent views changing the model
updateViewModel()
}
}
// MARK: - Intent(s)
private func updateViewModel() {
// update other properties based on the new state of the `model` one
}
}

SwiftUI: Forcing an Update

Normally, we're restricted from discussing Apple prerelease stuff, but I've already seen plenty of SwiftUI discussions, so I suspect that it's OK; just this once.
I am in the process of driving into the weeds on one of the tutorials (I do that).
I am adding a pair of buttons below the swipeable screens in the "Interfacing With UIKit" tutorial: https://developer.apple.com/tutorials/swiftui/interfacing-with-uikit
These are "Next" and "Prev" buttons. When at one end or the other, the corresponding button hides. I have that working fine.
The problem that I'm having, is accessing the UIPageViewController instance represented by the PageViewController.
I have the currentPage property changing (by making the PageViewController a delegate of the UIPageViewController), but I need to force the UIPageViewController to change programmatically.
I know that I can "brute force" the display by redrawing the PageView body, reflecting a new currentPage, but I'm not exactly sure how to do that.
struct PageView<Page: View>: View {
var viewControllers: [UIHostingController<Page>]
#State var currentPage = 0
init(_ views: [Page]) {
self.viewControllers = views.map { UIHostingController(rootView: $0) }
}
var body: some View {
VStack {
PageViewController(controllers: viewControllers, currentPage: $currentPage)
HStack(alignment: .center) {
Spacer()
if 0 < currentPage {
Button(action: {
self.prevPage()
}) {
Text("Prev")
}
Spacer()
}
Text(verbatim: "Page \(currentPage)")
if currentPage < viewControllers.count - 1 {
Spacer()
Button(action: {
self.nextPage()
}) {
Text("Next")
}
}
Spacer()
}
}
}
func nextPage() {
if currentPage < viewControllers.count - 1 {
currentPage += 1
}
}
func prevPage() {
if 0 < currentPage {
currentPage -= 1
}
}
}
I know the answer should be obvious, but I'm having difficulty figuring out how to programmatically refresh the VStack or body.
2021 SWIFT 1 and 2 both:
IMPORTANT THING! If you search for this hack, probably you doing something wrong! Please, read this block before you read hack solution!!!!!!!!!!
Your UI wasn't updated automatically because of you miss something
important.
Your ViewModel must be a class wrapped into ObservableObject/ObservedObject
Any field in ViewModel must be a STRUCT. NOT A CLASS!!!! Swift UI does not work with classes!
Must be used modifiers correctly (state, observable/observedObject, published, binding, etc)
If you need a class property in your View Model (for some reason) - you need to mark it as ObservableObject/Observed object and assign them into View's object !!!!!!!! inside init() of View. !!!!!!!
Sometimes is needed to use hacks. But this is really-really-really exclusive situation! In most cases this wrong way! One more time: Please, use structs instead of classes!
Your UI will be refreshed automatically if all of written above was used correctly.
Sample of correct usage:
struct SomeView : View {
#ObservedObject var model : SomeViewModel
#ObservedObject var someClassValue: MyClass
init(model: SomeViewModel) {
self.model = model
//as this is class we must do it observable and assign into view manually
self.someClassValue = model.someClassValue
}
var body: some View {
//here we can use model.someStructValue directly
// or we can use local someClassValue taken from VIEW, BUT NOT value from model
}
}
class SomeViewModel : ObservableObject {
#Published var someStructValue: Bool = false
var someClassValue: MyClass = MyClass() //myClass : ObservableObject
}
And the answer on topic question.
(hacks solutions - prefer do not use this)
Way 1: declare inside of view:
#State var updater: Bool = false
all you need to do is call updater.toggle()
Way 2: refresh from ViewModel
Works on SwiftUI 2
public class ViewModelSample : ObservableObject
func updateView(){
self.objectWillChange.send()
}
}
Way 3: refresh from ViewModel:
works on SwiftUI 1
import Combine
import SwiftUI
class ViewModelSample: ObservableObject {
private let objectWillChange = ObservableObjectPublisher()
func updateView(){
objectWillChange.send()
}
}
This is another solution what worked for me, using id() identifier. Basically, we are not really refreshing view. We are replacing the view with a new one.
import SwiftUI
struct ManualUpdatedTextField: View {
#State var name: String
var body: some View {
VStack {
TextField("", text: $name)
Text("Hello, \(name)!")
}
}
}
struct MainView: View {
#State private var name: String = "Tim"
#State private var theId = 0
var body: some View {
VStack {
Button {
name += " Cook"
theId += 1
} label: {
Text("update Text")
.padding()
.background(Color.blue)
}
ManualUpdatedTextField(name: name)
.id(theId)
}
}
}
Setting currentPage, as it is a #State, will reload the whole body.