Swiftui - Is There a Popviewcontroller Equivalent in Swiftui

Push, pop view controller equivalent in SwiftUI

Root :

window.rootViewController = UIHostingController(rootView: ContentView().environmentObject(Model()))

iOS version 13.1 :

class Model: ObservableObject {
@Published var pushed = false
}

struct ContentView: View {
@EnvironmentObject var model: Model

var body: some View {
NavigationView {
VStack {
Button("Push") {
self.model.pushed = true
}

NavigationLink(destination: DetailView(), isActive: $model.pushed) { EmptyView() }
}
}
}
}

struct DetailView: View {
@EnvironmentObject var model: Model

var body: some View {
Button("Bring me Back") {
self.model.pushed = false
}
}
}

Removing the default back button and adding our own will let us get through, until the bug gets fixed by Apple.

class Model: ObservableObject {
@Published var pushed = false
}

struct ContentView: View {
@EnvironmentObject var model: Model

var body: some View {
NavigationView {
VStack {
Button("Push") {
self.model.pushed = true
}

NavigationLink(destination: DetailView(), isActive: $model.pushed) { EmptyView() }
}
}
}
}

struct DetailView: View {
@EnvironmentObject var model: Model

var body: some View {
Button("Bring me Back") {
self.model.pushed = false
}
.navigationBarBackButtonHidden(true)
.navigationBarItems(leading: MyBackButton(label: "Back!") {
self.model.pushed = false
})
}
}

struct MyBackButton: View {
let label: String
let closure: () -> ()

var body: some View {
Button(action: { self.closure() }) {
HStack {
Image(systemName: "chevron.left")
Text(label)
}
}
}
}

more to refer

Is there a .onReappear equivalent in SwiftUI

Attach it instead to splash view directly, so once you come into condition of splash view it will run as expected.

    if(showSplash){
Text("Splash screen")
.onAppear(){ ... } // << move here !!
}

iOS SwiftUI: pop or dismiss view programmatically

This example uses the new environment var documented in the Beta 5 Release Notes, which was using a value property. It was changed in a later beta to use a wrappedValue property. This example is now current for the GM version. This exact same concept works to dismiss Modal views presented with the .sheet modifier.

import SwiftUI

struct DetailView: View {
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
var body: some View {
Button(
"Here is Detail View. Tap to go back.",
action: { self.presentationMode.wrappedValue.dismiss() }
)
}
}

struct RootView: View {
var body: some View {
VStack {
NavigationLink(destination: DetailView())
{ Text("I am Root. Tap for Detail View.") }
}
}
}

struct ContentView: View {
var body: some View {
NavigationView {
RootView()
}
}
}

What is equivalent to 'window.rootViewController' in WindowGroup - SwiftUI

With the help of comments and some tutorials, I reached out to the solution (Tested on iOS 15, Xcode 13.2.1):

Add the following code to the Main App Launcher.

struct MyApp: App {

@StateObject var appState = AppState.shared

var body: some Scene {
WindowGroup {
SplashScreenView().id(appState.environment)
}
}
}

And then I created the AppState class, which is the class that when changes I will change the window.

class AppState: ObservableObject {
static let shared = AppState()
@Published var environment = "Production"
}

And whenever I wanted to change the environment and do the same functionality of changing window in UIKit , do the following :

AppState.shared.environment = "Pre-Production"

How can I pop to the Root view using SwiftUI?

Setting the view modifier isDetailLink to false on a NavigationLink is the key to getting pop-to-root to work. isDetailLink is true by default and is adaptive to the containing View. On iPad landscape for example, a Split view is separated and isDetailLink ensures the destination view will be shown on the right-hand side. Setting isDetailLink to false consequently means that the destination view will always be pushed onto the navigation stack; thus can always be popped off.

Along with setting isDetailLink to false on NavigationLink, pass the isActive binding to each subsequent destination view. At last when you want to pop to the root view, set the value to false and it will automatically pop everything off:

import SwiftUI

struct ContentView: View {
@State var isActive : Bool = false

var body: some View {
NavigationView {
NavigationLink(
destination: ContentView2(rootIsActive: self.$isActive),
isActive: self.$isActive
) {
Text("Hello, World!")
}
.isDetailLink(false)
.navigationBarTitle("Root")
}
}
}

struct ContentView2: View {
@Binding var rootIsActive : Bool

var body: some View {
NavigationLink(destination: ContentView3(shouldPopToRootView: self.$rootIsActive)) {
Text("Hello, World #2!")
}
.isDetailLink(false)
.navigationBarTitle("Two")
}
}

struct ContentView3: View {
@Binding var shouldPopToRootView : Bool

var body: some View {
VStack {
Text("Hello, World #3!")
Button (action: { self.shouldPopToRootView = false } ){
Text("Pop to root")
}
}.navigationBarTitle("Three")
}
}

struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}

Screen capture



Related Topics



Leave a reply



Submit