Programmatic Navigation using SwiftUI| 使用 SwiftUI 进行程序化导航

用户头像
Daniel
关注
发布于: 2020 年 10 月 12 日

If you’re new to iOS development and have just started working with SwiftUI you may know NavigationLink as the way you are able to transition between different views in your app. What may be immediately less apparent is how you can do this programmatically.

For instance, if you made a login screen and the user presses a Login button — you may want to transition to the home screen of your application if the login success and display a pop-up if this fails. This is where programmatic navigation would come in.

If you’ve used UIKit in the past you will know about performSegue and pushViewController which are both ways to transition to a new view with code. With SwiftUI you cannot just call a function and have a new view pop up. You are going to have to use NavigationLink, a type of view in SwiftUI, to accomplish this.

Using NavigationLink to accomplish programmatic navigation

With SwiftUI comes the new @State property wrapper. The official Apple documentation does a pretty good job explaining how @State works. In essence, @State wraps your properties and whenever the value of the property changes “the view invalidates its appearance and recomputes the body.” You can think of it as the “trigger” for the navigation to occur.

NavigationLink is a SwiftUI button that will trigger navigation to another view when tapped. When it is tapped, the transition to the new view happens instantly. Since we may want to perform some functionality before transitioning to a new view (logging a user in, downloading some JSON data, etc.) we are going to use the isActive part of the constructor to get programmatic transition functionality.

We are going to use @State in combination with NavigationLink to get programmatic navigation in SwiftUI.

If you are following along from scratch, create a new SwiftUI view and do all of the following in that struct.

Declare a @State property in your struct initialized to false (in the case of a Bool).

@State var action: Bool = false



Create a NavigationLink and add it to the body of the view like so:

NavigationLink(desintation: NewView(), isActive: $action) {
EmptyView()
}



We set “isActive” equal to our state so the view will recompile when our state become true, and since it is true the NavigationLink will trigger.

The reason we want to put an EmptyView inside the NavigationLink is because the NavigationLink is not really a visual part of our UI. It just provides some under-the-hood functionality to our onscreen buttons. If you were to put something besides an EmptyView in there you would get a useless button on the screen — and nobody wants that!

Where in the above code snippet NewView() is the view you want to transition to. And the property you declared as @State is a Bool named action.

When you want to programmatically transition to your new view, you simply set action = true. And as the Apple documentation states, your view will recompute its body; since you set your state to true it will also go to the destination of your NavigationLink.

In the completed code below, for example, I called a function clicked() whenever a Text was tapped which set my state to true.

If you’ve done all the above and it’s still not working, you may want to make sure that your root view, or the view you are currently working with, has a NavigationView { } encapsulating everything in said View. If you don’t have that NavigationView somewhere in the view hierarchy whenever you try to trigger your navigation nothing will happen. Your state will just be set to true and the NavigationLink will do nothing.

Conclusion

Putting it all together you should have a basic view that looks something like this:

struct OpeningView : View {
@State var action: Bool = false
var body: some View {
NavigationView {
HStack {
NavigationLink(destination: NewView(), isActive: $action) {
EmptyView()
}
Text("Click me!")
.onTapGesture {
self.clicked()
}
}
}
}
func clicked() {
action = true
}
}



The use of HStack is because we are embedding multiples views in there, the NavigationLink will not show up on the screen since it is an EmptyView.



origin link: https://medium.com/swift2go/programmatic-navigation-using-swiftui-a0dfdad9b5fe

google translate如下

------------------------------------------------------------------------------------------------------------

如果您是iOS开发的新手,并且刚刚开始使用SwiftUI,您可能会知道您可以NavigationLink在应用程序中的不同视图之间进行转换。可能现在不太明显的是如何以编程方式执行此操作。

例如,如果您创建了一个登录屏幕,而用户按下了一个Login按钮,那么,如果登录成功,则可能需要转换到应用程序的主屏幕,如果登录失败,则显示一个弹出窗口。这就是程序化导航的地方。

如果您过去曾经使用过UIKit,那么您将了解performSegue以及pushViewController有两种方法可以使用代码过渡到新视图。使用SwiftUI,您不仅可以调用一个函数并弹出一个新视图。您将必须使用NavigationLink中的一种视图SwiftUI来完成此任务。

使用NavigationLink完成编程导航

随着SwiftUI而来的新@State属性包装。Apple官方文档在解释@State工作原理方面做得很好。本质上,@State包装您的属性,并且只要属性的值发生变化,“视图就会使外观无效并重新计算主体。” 您可以将其视为导航发生的“触发器”。

ANavigationLink是一个SwiftUI按钮,点击该按钮将触发导航到另一个视图。轻按一下,便会立即过渡到新视图。由于我们可能想在过渡到新视图(登录用户,下载一些JSON数据等)之前执行一些功能,因此我们将使用isActive构造函数的一部分来获取程序化过渡功能。

我们将与@State结合使用NavigationLink以在SwiftUI中获得程序化导航。

如果您从头开始,请创建一个新的SwiftUI视图,并在该结构中执行以下所有操作。

@State在您的结构中声明一个初始化为的属性false(对于Bool)。

创建一个NavigationLink并将其添加到视图主体中,如下所示:

我们将“ isActive”设置为等于我们的状态,以便当我们的状态为true时视图将重新编译,并且由于为true,NavigationLink将触发。

我们之所以要放在EmptyView其中NavigationLink是因为,NavigationLink它实际上并不是UI的可视部分。它只是为我们的屏幕按钮提供了一些后台功能。如果您要EmptyView在其中放置其他内容,则屏幕上会出现一个无用的按钮-没人想要!

上面代码片段NewView()中要转换到的视图。并且您声明为的属性@StateBool命名操作。

要以编程方式过渡到新视图时,只需设置action = true。正如Apple文档所述,您的视图将重新计算其主体。由于您将状态设置为true,因此它也将转到您的目的地NavigationLink

例如,在下面的完整代码中,clicked()每当Text点击a时,我都会调用一个函数,将状态设置为true

如果您已完成上述所有操作,但仍无法使用,则可能要确保您的根视图或当前正在使用的视图NavigationView { }将所有内容封装在said中View。如果NavigationView每次尝试触发导航时,视图层次结构中都没有该位置,则不会发生任何事情。您的状态将被设置为,true并且将NavigationLink不会执行任何操作。

结论

放在一起,您应该拥有一个看起来像这样的基本视图:

HStack的使用是因为我们在其中嵌入了多个视图,因为NavigationLink是EmptyView,所以它不会显示在屏幕上。



发布于: 2020 年 10 月 12 日 阅读数: 22
用户头像

Daniel

关注

还未添加个人签名 2019.02.27 加入

还未添加个人简介

评论

发布
暂无评论
Programmatic Navigation using SwiftUI| 使用SwiftUI进行程序化导航