Reputation: 1623
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
Reputation: 54426
Segue equivalents in SwiftUI 2 / iOS 14:
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
}
}
}
}
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
}
}
}
}
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
}
}
}
}
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
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
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
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