UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

Pass an @State variable to a Class so it can make changes to it

Forums > SwiftUI

The code below is what I'm trying to attempt. I want to pass the @State myName to the class, and allow changes to it when buttons are pressed. (There a whole bunch more, this is the only part I'm stuck on). When I run this, there are no errors, but it doesn't do anything. If I change it to self.helper.fieldBeingEdited = self.$myName, it gives an error. The class Helper has more code in it and it appears it has to be a class, not a struct. Is there an easy way to do this?

I should also mention that in the end, multiple textFields will use the same Helper, each sending their @State var to the Helper to be changed by the changeField().

class Helper: ObservableObject {

    @Published var fieldBeingEdited: String = ""

    func changeField() {
        fieldBeingEdited = "Something else"
    }
}

struct ContentView: View {
    @State var myName = "John"
    var helper = Helper()
    var body: some View {
        VStack {
            TextField("Your Name", text: $myName)
                .onTapGesture {
                    self.helper.fieldBeingEdited = self.myName
            }
            Button(action: {
                self.helper.changeField()
            }) {
                Text("Change")
            }
        }
    }
}

3      

Not sure why you used @State but if you use @ObservedObject this will change the @Published var

struct ContentView: View {
//    @State var myName = "John"
    @ObservedObject var helper = Helper()
    var body: some View {
        VStack {
            TextField("Your Name", text: $helper.fieldBeingEdited)
//                .onTapGesture {
//                    self.helper.fieldBeingEdited = self.myName
//            }
            Button(action: {
                self.helper.changeField()
            }) {
                Text("Change")
            }
        }
    }
}

commented out the code not used

3      

NigelGee is right, you need to use @ObservedObject, not @State. This is a general case, where you have an Observable class that Publishes whatever you want to keep track of and a subscriber class that observes those changes and is able to submit changes using the $ sign. I am not convinced that you need the button or the onTap, in this case, nor do you need the changeField method in the class, just change the Textfield and the class should change. Try this...

//
//  ContentView.swift
//  Hackit
//
//  Created by Mark Booth on 05/04/2020.
//  Copyright © 2020 Mark Booth. All rights reserved.
//

import SwiftUI

class Helper: ObservableObject {
    @Published var fieldBeingEdited: String = ""
}

struct ContentView: View {
//    @State var myName = "John"
    @ObservedObject var helper = Helper()
    var body: some View {
        VStack {
            TextField("Your Name", text: $helper.fieldBeingEdited)
            Text(helper.fieldBeingEdited)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

If you want to use the Helper class in a number of places you might need to declare it in the AppDelegate. Paul has some videos about the difference between State, Observed and Environment that are worth watching (in my case many times before it started to stick!)

4      

I had also asked this question on Stack Overflow. The answer I got there was this. I had updated the question there to clarify my intent. I want multiple textFields to be able to use the helper.

class Helper: ObservableObject {

    var fieldBeingEdited: Binding<String> = .constant("init")

    func changeField() {
        fieldBeingEdited.wrappedValue = "Something else"
    }
}

struct ContentView: View {
    @State var myName = "John"
    @State var otherName = "Paul"
    var helper = Helper()
    var body: some View {
        VStack {
            TextField("Your Name", text: $myName)
                .onTapGesture {
                    self.helper.fieldBeingEdited = self.$myName
            }
           TextField("Other Name", text: $otherName)
                .onTapGesture {
                    self.helper.fieldBeingEdited = self.$otherName
            }
            Button(action: {
                self.helper.changeField()
            }) {
                Text("Change")
            }
        }
    }
}

Tons of other code goes into it, but this step allowed me to make my own KeyboardAccessoryView, with Cancel, Clear and Done buttons. That part of it is now working like a charm.

3      

Hacking with Swift is sponsored by Essential Developer

SPONSORED Join a FREE crash course for mid/senior iOS devs who want to achieve an expert level of technical and practical skills – it’s the fast track to being a complete senior developer! Hurry up because it'll be available only until April 28th.

Click to save your free spot now

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.