【问题标题】:SwiftUI NavigationLink: Navigate to a destination view AFTER running account creation code successfullySwiftUI NavigationLink:成功运行帐户创建代码后导航到目标视图
【发布时间】: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)

        }

有没有更好的方法来做到这一点?从按钮触发运行帐户创建逻辑,然后激活虚拟导航链接以转换到下一个屏幕,这似乎是一种不好的做法。

【问题讨论】:

  • 我的答案(以及同一个问题中的另一个答案)可能很有趣:stackoverflow.com/a/57717462/1311272
  • 谢谢 Sajjon,这两个答案都很有趣。我正在尝试使用最 SwiftUI-y 的方式,所以@kontiki 的回答很有帮助,谢谢你指点我。使用 SwiftUI 对我来说最困难的部分是 1)在逻辑成功运行后在同一个 NavigationView“堆栈”中转换(即创建帐户以验证电子邮件视图),以及 2)转换到新的 NavigationView“堆栈”(即成功登录到带有自己的 NavigationView“堆栈”的主视图)。
  • 一般听起来你很难思考异步?从您的代码看来,您认为 VerifyEmail 的 NavigationLink 将在创建帐户后执行。事实并非如此,这与视图的定位有关,而不是执行顺序。
  • 你知道如何使用 UIKIT 做到这一点吗?
  • 是的,这就是我遇到的困难 - 如何让 NavigationLink 仅在帐户创建承诺链完成后才能激活。我在 UIKit 中构建了它,我正在尝试将所有视图和转换转换为 SwiftUI。现在我使用 PromiseKit 并在最后一个块中将新的视图控制器推送到堆栈上。我很难理解如何完成相同的异步工作,然后只有在成功的情况下才推送新的控制器。

标签: swiftui


【解决方案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
}

}

这里我们已经将actionStateNavigationLink 绑定在一起,因此每当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.

    【讨论】:

      猜你喜欢
      • 2019-11-11
      • 1970-01-01
      • 1970-01-01
      • 2021-12-30
      • 2020-06-16
      • 2020-04-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多