Home > Mobile >  Data loss on View Class, when keyboard appears
Data loss on View Class, when keyboard appears

Time:10-11

When ever I click on textField and key board appears, my list of data i.e coming from API is vanashing,

import SwiftUI
import ExytePopupView

struct Wallet: View {
    
    @State private var searchText = ""
    @State private var showCancelButton: Bool = false
    @ObservedObject var walltetVM = ShopViewModel()
    @State var showShopDetails: Bool = false
    @State var openShowDetails: Bool = false
    @State var selectedShopId:String = ""
    @State var selectedCouponDetail: CouponModel?

    
    var body: some View {
        
        NavigationView {
            VStack {
                // Search view
                VStack{
                    HStack {
                        Button {
                        } label: {
                            
                            Image(systemName: "magnifyingglass")
                                .foregroundColor(AppColors.semiBlue)
                                .frame(width: 20, height: 20, alignment: .center)
                            
                                .padding()
                        }
                        
                        
                        ZStack(alignment: .leading) {
                            if searchText.isEmpty {
                                Text(MaggnetLocalizedString(key: "Restaurant, Beauty shop...", comment: ""))
                                    .foregroundColor(AppColors.blackWhite)
                                    .font(Font(AppFont.lightFont(lightFontWithSize: 15)))
                            }
                            TextField("", text: $searchText)
                                .font(Font(AppFont.regularFont(regularFontWithSize: 15)))
                        }
                        .foregroundColor(AppColors.blackWhite)
                        .padding(.horizontal,10)
                        .padding(.leading,-15)
                        
                        Divider()
                        Button {
                        } label: {
                            HStack {
                                Image("places")
                                
                            }
                            .padding(.horizontal,20)
                            .padding(.leading,-12)
                        }
                        
                    }
                .frame(height: 45)
                .background(AppColors.fadeBackground)
                .clipShape(Capsule())
                }
                .padding(.horizontal)
                .padding(.vertical,10)
            
                ScrollView(.vertical) {
                    VStack{
                        
                        NavigationLink(destination:ShopDetail(shopId:self.selectedShopId)
                            .environmentObject(walltetVM),
                                       isActive: $openShowDetails) {
                            EmptyView()
                        }.hidden()
                        
                        Points()
                        
                        ForEach(0..<walltetVM.finalsCouponList.count,id: \.self){
                            index in
                        VStack{
                            
                            // SHOP LIST HEADERS
                            HStack{
                                Text(walltetVM.finalsCouponList[index].name)
                                    .multilineTextAlignment(.leading)
                                    .font(Font(AppFont.mediumFont(mediumFontWithSize: 15)))
                                    .foregroundColor(AppColors.blackWhite)
                                    .padding(.horizontal,10)
                                
                                Spacer()
                                Button {
                                } label: {
                                    Text(MaggnetLocalizedString(key: "viewAll", comment: ""))
                                        .font(Font(AppFont.regularFont(regularFontWithSize: 12)))
                                        .foregroundColor(AppColors.blackWhite)
                                        .padding()
                                        .frame(height: 27, alignment: .center)
                                        .background(AppColors.fadeBackground)
                                        .cornerRadius(8)
                                }
                            }
                            .padding()
                            
                            
                            // MAIN SHOP LIST
                            
                            VStack{
                                ScrollView(.horizontal,showsIndicators: false){
                                    HStack{
                                        ForEach(0..<walltetVM.finalsCouponList[index].couopons.count,id: \.self){
                                            indeX in
                                            Shops(coupons: walltetVM.finalsCouponList[index].couopons[indeX])
                                                .onTapGesture {
                                                    selectedShopId = walltetVM.finalsCouponList[index].couopons[indeX].businessId?.description ?? ""
                                                    print(selectedShopId)
                                                    selectedCouponDetail = walltetVM.finalsCouponList[index].couopons[indeX]
                                                    showShopDetails = true
                                                }
                                        }
                                    }
                                    .padding(.horizontal)
                                    
                                }
                                
                            }
                            .padding(.top,-5)
                            
                         }
                        .padding(.top,-5)

                        }
                    }
                }
                .blur(radius: showShopDetails ? 3 : 0)
                .popup(isPresented: $showShopDetails, autohideIn: 15, dismissCallback: {
                    showShopDetails = false
                }) {
                    ShopDetailPopUp(couponDeatil: self.selectedCouponDetail)
                        .frame(width: 300, height: 400)
                }
                .navigationBarTitle(Text("Wallet"),displayMode: .inline)
                .navigationBarItems(trailing: HStack{
                    Button {
                        
                    } label: {
                        Image("wishIcon").frame(width: 20, height: 20, alignment: .center)
                    }
                    Button {
                    } label: {
                        
                        Image("notifIcon").frame(width: 20, height: 20, alignment: .center)
                    }
                })
                
                .resignKeyboardOnDragGesture()
            }
            .onAppear(){
                walltetVM.getWallets()
            }
            .onReceive(NotificationCenter.default.publisher(for: NSNotification.openShopDetails))
                   { obj in
                       showShopDetails = false
                       openShowDetails.toggle()
                   }
            .environment(\.layoutDirection,Preferences.chooseLanguage == AppConstants.arabic ? .rightToLeft : .leftToRight)

        }
    }
}

struct Wallet_Previews: PreviewProvider {
    static var previews: some View {
        Wallet()
    }
}

bannerList is marked as @Published, API call working fine, but in same View class I have one search text field , when I tap on it all the data I was rendering from API get lost and disappears from list.

CodePudding user response:

You are holding a reference to your view model using ObservedObject:

@ObservedObject var walltetVM = ShopViewModel()

However, because you are creating the view model within the view, the view might tear down and recreate this at any moment, which might be why you are losing your data periodically.

If you use StateObject, this ensures that SwiftUI will retain the object for as long as the view lives, so the object won't be recreated.

@StateObject var walltetVM = ShopViewModel()

Alternatively, you could create the view model outside of the view and inject it into the view and keep using ObservedObject (but you'll still need to make sure the object lives as long as the view).

CodePudding user response:

I found something working but still not optimised solution instead of calling it on onAppear, I called API function in init method.

 init(){
        walltetVM.getWallets()
    }
  • Related