When a specific url is opened we enter to this function
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
I need to go to a specific screen. What I tried to do is to keep the contentView
instance and I tried to set index table to go to the other screen but it doesn't work because contentView
instance isn't linked correctly.
Here is what I tried:
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var contentView: some View {
let context = (UIApplication.shared.delegate as!
AppDelegate).persistentContainer.viewContext
// Remplacez cette partie par votre initialisation de ContentView
return ContentView().environment(\.managedObjectContext, context)
}...
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
guard let url = URLContexts.first?.url else {
return
}...
let a = contentView
if let contentView = (a as? ModifiedContent<ContentView, _EnvironmentKeyWritingModifier<NSManagedObjectContext>>)?.content {
// Faire quelque chose avec la contentView ici
contentView.indexTab = 2
}
My ContentView
:
struct ContentView: View {
@State public var indexTab = 0 ...
body:
var body: some View {
VStack{
if(indexTab > -1){
TCTabBar(images: [
Image(systemName: "house.fill"),
Image(systemName: "cart.fill"),
Image(systemName: "heart.fill"),
Image(systemName: "gear")
], tabIndex: indexTab, contentTabs: [
AnyView(ProductCatalog(products: $items, cart: $cart, favorites: $favorites)),
AnyView(CartView(items: $cart)),
AnyView(ProductCatalog(products: $favorites, cart: $cart, favorites: $favorites)),
AnyView(SettingsView())
])
}
}.task {
ContentViewModel.shared.contentView = self
}
the problem is that ContentView
never update from SceneDelegate
.
How can I correct this problem?
You definitely don't want to reference contentView
directly and modify it because the view can be recreated at any point.
What you should do instead is create some kind of ViewModel or some other kind of object holding on to the global state (in this case, your indexTab
). This object can then conform to the ObservableObject
protocol and have @Published public var indexTab = 0
defined.
You can initialise a single instance of this object in your SceneDelegate and pass it down to your view via @EnvironmentObject var stateStore: StateStore
So you will end up with something like this.
class StateStore: ObservableObject {
@Published public var indexTab = 0
}
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var stateStore: StateStore = .init()
var contentView: some View {
return ContentView()
...
.environmentObject(stateStore) // Pass it down via Environment
}
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
guard let url = URLContexts.first?.url else { return }
...
stateStore.indexTab = 2
}
struct ContentView: View {
@EnvironmentObject var stateStore: StateStore // This will traverse environment and find matching object based on type
var body: some View {
TCTabBar(
images: [ ... ],
tabIndex: stateStore.indexTab, // Use published value here
contentTabs: [ ... ]
)
}
}
}