SwiftUI NavigationLink:成功运行帐户创建代码后导航到目标视图
Posted
技术标签:
【中文标题】SwiftUI NavigationLink:成功运行帐户创建代码后导航到目标视图【英文标题】:SwiftUI NavigationLink: Navigate to a destination view AFTER running account creation code successfully 【发布时间】:2019-08-28 18:00:53 【问题描述】:我想运行帐户创建逻辑,然后如果成功,则转换到目标视图。否则,我将提供错误表。 NavigationLink 立即转换到点击的目标视图。
如果我使用 isActive 重载和一个空字符串作为文本创建一个虚拟 NavigationLink(这会创建一个零帧视图),我可以让它工作。然后,我使用向用户提供的 Button 切换 isActive 属性,该按钮首先运行帐户创建逻辑,并在链的末尾将 NavigationLink 切换为活动状态。我在 NavigationView 中。
@State private var isActive: Bool = false
NavigationView
// Name, Email, Password Textfields here
// Button to run account creation logic:
Button(action:
// Account creation promise chain here, then...
self.isActive.toggle()
)
Text("Create Account")
// Phantom navigation link:
NavigationLink("", destination: VerifyEmailView(email: email), isActive: self.$isActive)
有没有更好的方法来做到这一点?从按钮触发运行帐户创建逻辑,然后激活虚拟导航链接以转换到下一个屏幕,这似乎是一种不好的做法。
【问题讨论】:
我的答案(以及同一个问题中的另一个答案)可能很有趣:***.com/a/57717462/1311272 谢谢 Sajjon,这两个答案都很有趣。我正在尝试使用最 SwiftUI-y 的方式,所以@kontiki 的回答很有帮助,谢谢你指点我。使用 SwiftUI 对我来说最困难的部分是 1)在逻辑成功运行后在同一个 NavigationView“堆栈”中转换(即创建帐户以验证电子邮件视图),以及 2)转换到新的 NavigationView“堆栈”(即成功登录到带有自己的 NavigationView“堆栈”的主视图)。 一般听起来你很难思考异步?从您的代码看来,您认为 VerifyEmail 的 NavigationLink 将在创建帐户后执行。事实并非如此,这与视图的定位有关,而不是执行顺序。 你知道如何使用 UIKIT 做到这一点吗? 是的,这就是我遇到的困难 - 如何让 NavigationLink 仅在帐户创建承诺链完成后才能激活。我在 UIKit 中构建了它,我正在尝试将所有视图和转换转换为 SwiftUI。现在我使用 PromiseKit 并在最后一个块中将新的视图控制器推送到堆栈上。我很难理解如何完成相同的异步工作,然后只有在成功的情况下才推送新的控制器。 【参考方案1】:有一种非常简单的方法可以处理您的视图状态和NavigationLinks
。
您可以通过将tag
绑定到它来通知您的NavigationLink
自行执行。
然后您可以设置-取消设置标签并控制您的NavigationLink
。
struct SwiftView: View
@State private var actionState: Int? = 0
var body: some View
NavigationView
VStack
NavigationLink(destination: Text("Destination View"), tag: 1, selection: $actionState)
EmptyView()
Text("Create Account")
.onTapGesture
self.asyncTask()
func asyncTask()
//some task which on completion will set the value of actionState
self.actionState = 1
这里我们已经将actionState
与NavigationLink
绑定在一起,因此每当actionState
的值发生变化时,它将与与我们的NavigationLink
关联的tag
进行比较。
在您将actionState
的值设置为等于与我们的NavigationLink
关联的tag
之前,您的目标视图 将不可见。
这样,您可以创建任意数量的NavigationLinks
,并且可以通过更改一个Bindable
属性来控制它们。
谢谢,希望对你有帮助。
【讨论】:
提示:使用nil
作为动作状态的初始值是行不通的。在我的情况下,导航链接仍然立即执行。【参考方案2】:
以 Mohit 的回答为基础,使用封装屏幕状态的枚举使 Swifty 变得更加快捷:
enum ActionState: Int
case setup = 0
case readyForPush = 1
struct SwiftView: View
@State private var actionState: ActionState? = .setup
var body: some View
NavigationView
VStack
NavigationLink(destination: SomeView, tag: .readyForPush, selection: $actionState)
EmptyView()
Text("Create Account")
.onTapGesture
self.asyncTask()
func asyncTask()
//some task which on completion will set the value of actionState
self.actionState = .readyForPush
【讨论】:
【参考方案3】:您可以将目标视图包装在惰性视图中以防止立即调用。这是一个例子:
struct LazyView<Content: View>: View
let build: () -> Content
init(_ build: @autoclosure @escaping () -> Content)
self.build = build
var body: Content
build()
最终,像这样调用它:
NavigationLink(destination: LazyView(Text("Detail Screen")))//your code
我写了一篇完整的博客文章,涵盖了 SwiftUI 中 NavigationLinks 的其他一些缺陷。 Refer here.
【讨论】:
以上是关于SwiftUI NavigationLink:成功运行帐户创建代码后导航到目标视图的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI 上的 NavigationLink 两次推送视图
SwiftUI:NavigationLink 内的水平 ScrollView 会中断导航