以编程方式导航到SwiftUI中的新视图

zgo*_*ski 3 swift swiftui

描述性示例:

登录屏幕,用户点击“登录”按钮,执行请求,UI显示等待指示器,然后在成功响应后,我想自动将用户导航到下一个屏幕。

如何在SwiftUI中实现这种自动转换?

Mo *_*ani 8

成功登录后,可以使用登录视图替换下一个视图。例如:

struct LoginView: View {
    var body: some View {
        ...
    }
}

struct NextView: View {
    var body: some View {
        ...
    }
}

// Your starting view
struct ContentView: View {

    @EnvironmentObject var userAuth: UserAuth 

    var body: some View {
        if !userAuth.isLoggedin {
            LoginView()
        } else {
            NextView()
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

您应该在数据模型中处理登录过程,并使用绑定(例如)@EnvironmentObject传递isLoggedin给视图。

注意:在Xcode中11.0版测试4,以符合协议“BindableObject”willChange属性已被添加

import Combine

class UserAuth: ObservableObject {

  let didChange = PassthroughSubject<UserAuth,Never>()

  // required to conform to protocol 'ObservableObject' 
  let willChange = PassthroughSubject<UserAuth,Never>()

  func login() {
    // login request... on success:
    self.isLoggedin = true
  }

  var isLoggedin = false {
    didSet {
      didChange.send(self)
    }

    // willSet {
    //       willChange.send(self)
    // }
  }
}
Run Code Online (Sandbox Code Playgroud)

  • @MoRezaFarahani我正在使用beta 7,而UserAuth现在是一个ObservableObject。在我的ContentView中,在“ var body:some View”行中,出现错误“函数声明了不透明的返回类型,但在其主体中没有可从其推断基础类型的返回语句”。 (2认同)
  • 我是 SwiftUI 新手,但我完全遵循了这一点并收到此错误:致命错误:找不到 UserAuth 类型的 ObservableObject 。UserAuth 的 View.environmentObject(_:) 作为此视图的祖先可能会丢失。: 文件 SwiftUI,第 0 行。此错误仅在运行时出现。 (2认同)

Rya*_*yan 6

为了将来参考,由于许多用户报告收到错误“函数声明不透明的返回类型”,从@MoRezaFarahani 实现上述代码需要以下语法:

struct ContentView: View {

    @EnvironmentObject var userAuth: UserAuth 

    var body: some View {
        if !userAuth.isLoggedin {
            return AnyView(LoginView())
        } else {
            return AnyView(NextView())
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

这适用于 Xcode 11.4 和 Swift 5

  • 这个动画正确吗?我想要两个视图之间的推送动画。 (2认同)

小智 5

struct LoginView: View {
    
    @State var isActive = false
    @State var attemptingLogin = false
    
    var body: some View {
        ZStack {
            NavigationLink(destination: HomePage(), isActive: $isActive) {
                Button(action: {
                    attlempinglogin = true
                    // Your login function will most likely have a closure in 
                    // which you change the state of isActive to true in order 
                    // to trigger a transition
                    loginFunction() { response in
                        if response == .success {
                            self.isActive = true
                        } else {
                            self.attemptingLogin = false
                        }
                    }
                }) {
                    Text("login")
                }
            }
            
            WaitingIndicator()
                .opacity(attemptingLogin ? 1.0 : 0.0)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

将导航链接与 $isActive 绑定变量一起使用