1

I have a simple class to store some data in my SwiftUI app:

final class UserData: ObservableObject  {
    @Published var id = 1
    @Published var name = "Name"
    @Published var description = "Initial text"
}

I also defined it as EnvironmentObject in the main app struct:

ContentView(document: file.$document)
    .environmentObject(UserData())

In my Content View, I embedded a UIKit Text View:

EditorTextView(document: $document.text)

Where EditorTextView is a UITextView that is applied through UIViewRepresentable.

Now, what I'm trying to do is to update UserData within EditorTextView, like, storing some user input into UserData.description. So I defined the class inside my Coordinator as follows (the code is just for example):

class Coordinator: NSObject, UITextViewDelegate {
    @ObservedObject var userData = UserData()
    ...
    // Somewhere in the code, I update UserData when user taps Enter:
    func textViewDidChange(_ textView: UITextView) {
        if (textView.text.last == "\n") {
            userData.description = "My New Text"
        }
    }

My problem is:

Although it is updated with "My New Text" (as debugger shows), the value of userData.description is re-initiated again with the value "Initial text". It's like if UserData class is created everytime.

I tried to use @StateObject instead of @ObservedObject, but it doesn't make a difference.

Sami Almalki
  • 588
  • 2
  • 17

1 Answers1

3

"It's like if UserData class is created everytime."

It is created everytime, right here:

class Coordinator: NSObject, UITextViewDelegate {
    @ObservedObject var userData = UserData()  // <--- here

Try this instead, and pass the UserData in from outside:

class Coordinator: NSObject, UITextViewDelegate {
    @ObservedObject var userData: UserData

Typically you would also do this in your main app struct:

@StateObject var userData = UserData()
...
ContentView(document: file.$document).environmentObject(userData)
  • Thanks, but how to initialize userData in the Coordinator init function? `init(_ parent: EditorTextView) {` `self.parent = parent` `}` – Sami Almalki Jul 03 '21 at 02:54
  • You have "@ObservedObject var userData: UserData" in the parent. Then in Coordinator you have the init with the parent, then you can refer to it in Coordinator, like this: "self.parent.userData". – workingdog support Ukraine Jul 03 '21 at 03:13
  • So I moved `@ObservedObject var userData: UserData` from the coordinator to the parent which is EditorTextView, but errors starts to appear. I've created a Minimal Reproducible Example, please take a look [here](https://www.dropbox.com/s/7ul8jpc8ixo693q/reprex.zip?dl=0) – Sami Almalki Jul 03 '21 at 19:18
  • I cannot download you code from that site. From my brief look at it: it is clear to me that you need to read up on ObservedObject and EnvironmentObject, how to use and pass them from one view to the next. A simple how to use is at: https://www.hackingwithswift.com/quick-start/swiftui/how-to-use-environmentobject-to-share-data-between-views In your ContentView you don't even have: "@EnvironmentObject var userData: UserData". My advice is, study a bit more on ObservedObject and EnvironmentObject. – workingdog support Ukraine Jul 03 '21 at 23:36