2

In essence, I'm learning by creating a simple app that takes an ISBN and returns the book information. I've created a view file to display this information along with a text entry for capturing the ISBN. The logic side of things as pertaining to getting the information from the internet is fine, however, when I try to update the view with the modified variables, it only prints them as declared, and NOT redrawing them after modification. Any advice would be appreciated. Thanks!

This specific example references @Published var test = "Testing 1 2 3 as the default, and after the search, the var is modified to test = modified text which is then printed in the text view of TestView.swift. The print statement correctly displays the modified text, however it does not update in the view in which it is passed. The goal is to pass the final dictionary, but for testing purposes I'm using a simple string variable.

TestFile.swift

import Foundation
import SwiftyXMLParser
import SwiftUI

class getdata: ObservableObject {
    
    @Published var outputDict: [String:String] = [:]
    @Published var test = "Testing 1 2 3"

    .
    .

    //code to grab xml from url

    .
    .

    func parseData(input: String) {
        var title: String?
        var author: String?
        let xml = try! XML.parse(input)
        if let text = xml["GoodreadsResponse", "book", "title"].text {
            title = text
            outputDict["title"] = title
        }
        if let text = xml["GoodreadsResponse", "book", "authors", "author", "name"].text {
            author = text
            outputDict["author"] = author
        }
        print("Title: \(outputDict["title"]!), Author: \(outputDict["author"]!)")
        test = "modified text"
        print(test)
    }
}

TestView.swift

import SwiftUI

struct testView: View {
    
    @State var textEntry: String = ""
    @ObservedObject var viewModel: getdata
    
    var body: some View {
        let try1 = getdata()
        VStack {
            TextField("Enter ISBN", text: $textEntry)
                .padding()
            Button(action: {try1.getData(bookID: textEntry)}, label: {
                Text("Search")
            })
            Text("Title: \(self.viewModel.test)")
        }
    }
}
    

struct testView_Previews: PreviewProvider {
    static var previews: some View {
        testView(viewModel: getdata())
    }
}
1
  • Make life simpler for yourself. Class names are CamelCased, so your data class should be GetData. What is try1.getData(bookID: textEntry)? I'm surprised your code compiles. Commented Jul 18, 2021 at 16:26

1 Answer 1

1

Although I don't think your example compiles, and you haven't provided the definitions of some of the functions, I can point you at one error:

Inside the body of the view you are creating a new Observable object:

let try1 = getdata()

And your Button calls messages on this:

Button(action: {try1.getData(bookID: textEntry)}...

But your TextView reads from the original viewModel:

Text("Title: \(self.viewModel.test)")

You are interacting with try1, but deriving your view from viewModel. They are separate objects.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you! It was a dumb mistake on my part. The "try1" was from an older attempt at accessing the method of another swift file. Once I learned how to use, and implement @Published, I revoked that but never changed it in the code. I'm surprised it compiled too now that I realize the error! But it is working as expected now.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.