0

Getting error here - selectedTab = tab.getTab()

Fatal error: No ObservableObject of type SelectedTab found. A View.environmentObject(_:) for SelectedTab may be missing as an ancestor of this view.

Also tried this - https://www.hackingwithswift.com/forums/swiftui/fatal-error-no-observableobject-of-type-order-found/3208

    class SelectedTab: ObservableObject {
        @Published var tab:String = "Home"
        
        func setTab(tabName: String) {
            tab = tabName
        }
        
        func getTab() -> String {
            return tab
        }
    }
    
    
    
    struct TabBarContentView: View {
        @EnvironmentObject var tab: SelectedTab
        
        var body: some View {
            Home().environmentObject(tab)
        }
    }
    
    struct TabBarContentView_Previews: PreviewProvider {
        
        
        static var previews: some View {
            Group {
                TabBarContentView()
                    .previewDevice(PreviewDevice(rawValue: "iPhone 12 Pro Max"))
                    .previewDisplayName("iPhone 12 Pro Max") 
            }
        }
    }
    
struct Home: View {
    @EnvironmentObject var tab: SelectedTab
    @State var selectedTab = "Home"

init() {
    UITabBar.appearance().isHidden = true
    selectedTab = tab.getTab()
}

var body: some View{
    NavigationView() {
        ZStack(alignment: .bottom, content: {
            
            TabView(selection: $selectedTab){
                HomeTab()
                NewsTab()
                ProfileTab()
                MoreTab()
            }
        }
        }
}

}

vipinsaini0
  • 541
  • 1
  • 7
  • 26
  • As the error says, the object needs to be injected into the environment in an ancestor to `TabBarContentView` – Paulw11 Jul 07 '21 at 11:27
  • already done - struct TabBarContentView: View { @EnvironmentObject var tab: SelectedTab var body: some View { Home().environmentObject(tab) } } – vipinsaini0 Jul 07 '21 at 11:53
  • No, that is trying to get an object *from the environment*, but it isn't there so you get the error. – Paulw11 Jul 07 '21 at 11:55

2 Answers2

1

you have:

struct Home: View {
@EnvironmentObject var tab: SelectedTab   // <--- here
....

and similarly for TabBarContentView.

This implies that you have in your parent view, for example the App, something like this:

import SwiftUI

@main
struct MyApp: App {
    @StateObject var tab = SelectedTab()   // <--- here
    var body: some Scene {
        WindowGroup {
            Home().environmentObject(tab)  // <--- here
        }
    }
}  

If you don't have something like this, then you get the error you see.

0

In Home, tab is not available during initialization.

struct Home: View {
    @EnvironmentObject var tab: SelectedTab
    @State var selectedTab = "Home"
    
    init() {
        UITabBar.appearance().isHidden = true
        selectedTab = tab.getTab()  // tab is not available here.
    }

    ------
}


There are two ways to fix this issue.

1.

Change the signature of home. Pass selectedTab from TabBarContentView.

struct Home: View {
    @EnvironmentObject var tab: SelectedTab
    
    @State var selectedTab = "Home"
    
    init(selectedTab: String) {
        UITabBar.appearance().isHidden = true
        self.selectedTab = selectedTab
    }

    ---
 }
struct TabBarContentView: View {
    @EnvironmentObject var tab: SelectedTab
    
    var body: some View {
        Home(selectedTab: tab.getTab()).environmentObject(tab)
    }
}

2.

Use @ObservedObject instead of @EnvironmentObject in Home.

struct Home: View {
    @ObservedObject var tab: SelectedTab
    
    @State var selectedTab = "Home"
    
    init(tab: SelectedTab) {
        UITabBar.appearance().isHidden = true
        self.tab = tab
        self.selectedTab = tab.getTab()
    }
}

struct TabBarContentView: View {
    @EnvironmentObject var tab: SelectedTab
    
    var body: some View {
        Home(tab: tab)
    }
}


If you do not need SelectedTab for any other purpose, go for the 2nd approach.

mahan
  • 12,366
  • 5
  • 48
  • 83