Search code examples
swiftuiobservedobjectzstack

SwiftUI didn't update the view while observedObject changed


I'm doing a login and display data application. While the user login, the data will be displayed correctly. While I logout and login another account, the data supposed to be update by the observedObject which call the function to be reload the data. But while I login into the apps, the home view still display the old data by previous account. I don't know what the problem. I tried many way to solve even I clear the data in class while I Logout, however, the view still didn't update. Looking for help, tq.

struct ContentView: View {
    @EnvironmentObject var authService:AuthService
    var body: some View{
        ZStack{
            if(!authService.signedIn){
                RegisterView()
            }
            else{
                HomePageView()
            }
        }
    }}
struct HomePageView: View {
    @ObservedObject var shopList:ShopJSON = .shared

    var body: some View {
        
        TabView{
            HomePromotionView(shopList: shopList)
                .tabItem {
                        Image(systemName: "house")
                }.tag(1)

            NavigationView{
                BookingView()
            }
                .tabItem {
                    Image(systemName: "calendar")
                }.tag(3)
        }
        .onAppear(perform: ShopJSON.shared.reload) //I try to force reload data.
    }
}
struct HomePromotionView: View {
    @State private var selectedSegment = 0
    @ObservedObject var shopList : ShopJSON

    private let homeSegment = ["PROMOTION", "HISTORY", "MESSAGE"]
    
    var body: some View {
        NavigationView {
            
            VStack {
                ScrollView(.horizontal, showsIndicators: false){
                    
                    HStack{
                        
                        ForEach(shopList.shops){ item in
                            MerchantBar(name:item.name!, icon: item.icon!, id: item.shopID!)
                        }
class ShopJSON: ObservableObject {
    
    @Published var shops = [Shops]()
    @Published var bcsts = [Bcast]()
    @Published var selectedID : Int?
    static let shared = ShopJSON()

    let auth = UserDefaults.standard.string(forKey: "Auth")
    
    private init() {
        load()
    }
    func reload() {
        load()
    }
    func clear() {
        self.shops = [Shops]()
        self.bcsts = [Bcast]()
        self.selectedID = nil
    }
    func load() {
        
        let url = URL(string: "https://12345/shop/")!
        var request = URLRequest(url: url)
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.setValue(self.auth, forHTTPHeaderField: "token")
        request.httpMethod = "GET"
        
        URLSession.shared.dataTask(with: request) { data, response, error in
            guard let data = data else {
                print("No data in response: \(error?.localizedDescription ?? "Unknown error").")
                return
            }
            if let decodedShops = try? JSONDecoder().decode(Json4Swift_Base.self, from: data) {
                DispatchQueue.main.async {
                    self.shops = decodedShops.shops!
                    self.bcsts = decodedShops.bcast!

Logout button

            Text("Sign Out")
                .foregroundColor(Color.gray)
                .onTapGesture {
                    self.authService.signOut()
                    UserDefaults.standard.set(nil, forKey: "Auth")
                    //self.shopList.clear()       //force clean data but view didn't update while login with another account
            }

Solution

  • The problem is I declare the auth token in class. While the user logout the token inside the class didn't update. It will still use the old token to get the result.

    The solution is just get the token inside the function instead of declare in the class

    Solution:

    func load() {
            let url = URL(string: "https://12345/shop/")!
            var request = URLRequest(url: url)
            request.setValue("application/json", forHTTPHeaderField: "Content-Type")
            let auth = UserDefaults.standard.string(forKey: "Auth")
            request.setValue(auth, forHTTPHeaderField: "token")
            request.httpMethod = "GET"