Fonctionnement de ObservableObject

Bonjour à tous,
J'utilise désormais SwiftUI depuis le début de l'année et les évolutions de cette semaine me donnent encore plus envie de continuer. Cependant je note des problèmes.

J'ai le code suivant :

 public class ProductFetcher : ObservableObject {
     @Published var product = [Product]()

    init() {
         print("Init ProcductFetcher...")
    }

}

Je n'ai pas de référence à la classe ProductFetcher dans la première vue ContentView.
Pourtant quand je lance l'application, j'ai ceci qui s'affiche :

 Init ProcductFetcher...

Pourriez-vous m'aider à comprendre ? est-ce le comportement de ObservableObject qui implique ceci ?

Merci.

Mots clés:

Réponses

  • PyrohPyroh Membre
    Il va falloir nous montrer le code de la vue.
  • Il n'y a pas un @EnvironmentObject dans ton application ?

  • heliohelio Membre

    Non pas de @EnvironmentObject

    Voici la vue qui utilise la classe :

    import SwiftUI
    
    struct ExplorerView : View {
    
    @ObservedObject var fetcher = ProductFetcher()
    
    
    var body: some View {
    
        NavigationView {
    
            List {
    
                    ForEach(fetcher.products, id: \.self) { product in
                        NavigationLink(destination: ProductDetail()) {
                            ProductRow(product: product)
                        }
                    }
    
    
            }
            .navigationBarTitle("Products", displayMode: .large)
            .onAppear {
                     UITableView.appearance().separatorColor = .clear
    
            }
        }
    
    }
    
    }
    
  • heliohelio Membre

    Et ContentView :

    import SwiftUI
    
    struct ContentView: View {
    @State private var selection = 0
    
    #if targetEnvironment(macCatalyst)
    var body: some View {
        SplitView()
    }
    #else
    var body: some View {
        TabbarView()
    }
    #endif
    
    }
    
    // MARK: - iOS implementation
    struct TabbarView: View {
    @State var selectedTab = Tab.home
    
        enum Tab: Int {
            case home, explorer
        }
    
        func tabbarItem(text: String, image: String) -> some View {
            VStack {
                Image(systemName: image)
                    .imageScale(.large)
                Text(text)
            }
        }
    
        var body: some View {
            TabView(selection: $selectedTab) {
    
                HomeView().tabItem {
                    self.tabbarItem(text: "Home", image: "house")
    
                }.tag(Tab.home)
    
                ExplorerView().tabItem {
                    self.tabbarItem(text: "Explorer", image: "desktopcomputer").tag(Tab.explorer)
                 }.tag(Tab.explorer)
    
            }
    
    }
    }
    
    
    
    struct SplitView: View {
    
    var body: some View {
    
        Text("SplitView")
    
    }
    }
    
    
     struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
    }
    
  • DrakenDraken Membre
    juin 2020 modifié #6

    C'est normal. Le TabView crée les vues HomeView() et ExplorerView() à l'initialisation, pour pouvoir passer de l'une à l'autre rapidement.

    Même si ExplorerView() n'est pas affichée au démarrage de l'application, elle est quand même créé, ce qui provoque la création de la classe ProductFetcher.

    Ce n'est pas le fonctionnement de @ObservableObject qui te posait problème, mais celui de TabView.

    Pour vérifier cette hypothèse, j'ai tapé un petit programme de test.

    import SwiftUI
    
    class Modele1 : ObservableObject {
      init() {
        print ("Init Modele 1")
      }
    }
    
    class Modele2 : ObservableObject {
      init() {
        print ("Init Modele 2")
      }
    }
    
    
    struct Vue1 : View {
      @ObservedObject var modele = Modele1()
      var body: some View {
        Text("VUE 1")
      }
    }
    
    struct Vue2 : View {
      @ObservedObject var modele = Modele2()
      var body : some View {
        Text("VUE 2")
      }
    }
    
    
    struct ContentView: View {
    
      enum Etat:Int {
        case etat1, etat2
      }
    
      @State var selecteur = Etat.etat1
    
        var body: some View {
          TabView(selection: $selecteur) {
            Vue1().tag(Etat.etat1)
            Vue2().tag(Etat.etat2)
          }
        }
    }
    
    struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
            ContentView()
        }
    }
    

    Les deux vues sont bien créées au démarrage :

    Init Modele 1
    Init Modele 2

    De base, j'aurais pensé que le TabView créait et détruisait les vues en fonction des besoins, mais non manifestement.

  • heliohelio Membre

    Merci Draken, je ne pensais pas que le TabView fonctionnait comme cela !

  • @helio a dit :
    Merci Draken, je ne pensais pas que le TabView fonctionnait comme cela !

    Moi non plus ! J’y ai pensé en regardant ton problème. Puis j’ai écris un petit test pour vérifier.

Connectez-vous ou Inscrivez-vous pour répondre.