BlueSpud
BlueSpud

Reputation: 1623

Presenting New Views in SwiftUI Without a Button

So I want to present a new view using SwiftUI, without the user having to tap a button, since NavigationButton would work with that. Here is an example

struct ContentView : View {

    var model: Model

    var body: some View {
        NavigationView {
            Text("Hello World")
        }.onAppear {
            if model.shouldPresent {
                // present a new view
            }
        }
    }
}

In the onAppear I want to include some code that will push a new view onto the navigation stack.

Upvotes: 24

Views: 19358

Answers (4)

pawello2222
pawello2222

Reputation: 54426

SwiftUI 2

Segue equivalents in SwiftUI 2 / iOS 14:

  • Show (Push)
struct ContentView: View {
    @State var showSecondView = false

    var body: some View {
        NavigationView {
            Text("First view")
                .background(NavigationLink("", destination: Text("Second view"), isActive: $showSecondView))
        }
        .onAppear {
            DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
                showSecondView = true
            }
        }
    }
}
  • Show Detail (Replace)
struct ContentView: View {
    @State private var showSecondView = false

    var body: some View {
        NavigationView {
            if showSecondView {
                Text("Second view")
            } else {
                Text("First view")
            }
        }
        .onAppear {
            DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
                showSecondView = true
            }
        }
    }
}
  • Present Modally
struct ContentView: View {
    @State private var showSecondView = false

    var body: some View {
        NavigationView {
            Text("First view")
        }
        .sheet(isPresented: $showSecondView) {
            Text("Second view")
        }
        .onAppear {
            DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
                showSecondView = true
            }
        }
    }
}
  • Present as Full Screen
struct ContentView: View {
    @State private var showSecondView = false

    var body: some View {
        NavigationView {
            Text("First view")
        }
        .fullScreenCover(isPresented: $showSecondView) {
            Text("Second view")
        }
        .onAppear {
            DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
                showSecondView = true
            }
        }
    }
}

Note: I added DispatchQueue.main.asyncAfter(deadline: .now() + 1) so you can see the transition. You can remove it and the transition will start immediately.

Upvotes: 3

Div
Div

Reputation: 1603

Inside your view:

@State var present = true

var body: some View {
    NavigationLink(destination: DestinationView(), isActive: $present) {
        EmptyView()
    }
}

This code presents DestinationView as soon as the NavigationLink loads. The crucial part is the isActive parameter, which programmatically triggers the transition to the other View.

You could rewrite as follows

@State var present = false

var body: some View {
    NavigationLink(destination: DestinationView(), isActive: $present) {
        Button { 
            present = true
        } label: { Text("Present") }
    }
}

To manually create a navigation button.

Upvotes: 1

SMP
SMP

Reputation: 1669

Here's a way to present view as a Modal.

struct PresentOnloadView: View {
    var body: some View {
        HStack {
            Text("Hey there")
            }
            .presentation(Modal(HelloView(), onDismiss: nil))
        }
}

struct HelloView: View {
    var body: some View {
        Text("Whats up! 👻")
    }
}

Similarly, if you're looking to control whether to present or not using a variable, you can do something like this..

struct PresentOnloadControlledView : View {
  @State var sayHello = false

    var body: some View {
        HStack {
                Text("What's up!")
            }
            .onAppear(perform: {
                // Decide whether to show another view or not here
                self.sayHello = true
            })
            .presentation(sayHello ? Modal(HelloView()) : nil)
    }
}

As of Version 11.0 beta 4.presentation and Modal has been deprecated.

Not to worry! .sheet saves the day!

struct PresentOnloadControlledView : View {
  @State var sayHello = false

    var body: some View {
        HStack {
            Text("What's up!")
        }
        .onAppear(perform: {
            // Decide whether to show another view or not here
            self.sayHello = true
        })
        .sheet(isPresented: $sayHello) {
            HelloView()
        }
    }
}

Upvotes: 12

zoecarver
zoecarver

Reputation: 6403

You can simply put the logic inside the NavigationView. Like this:

@State var x = true;

var body : some View {
    NavigationView {
        if x {
            Text("Hello")
            Button(action: {
                self.x = false;
            }, label: { Text("Click Me") })
        } else {
            Text("World")
        }
    }
}

Upvotes: -2

Related Questions