SwiftUI 成功后自动转到下一个视图

Posted

技术标签:

【中文标题】SwiftUI 成功后自动转到下一个视图【英文标题】:SwiftUI automatically go to next view on success 【发布时间】:2020-07-06 17:32:27 【问题描述】:

我有一个执行 http 请求的登录视图。一旦我们得到 http 响应,我们就知道用户是否可以进入下一个视图。我想知道如何在不点击的情况下触发下一个视图?我不想做一张纸,因为我想获得全屏模式。我一直在看这个Go to a new view using SwiftUI,但没有运气。从下面的代码中,当我单击 Press on me 导航链接时,我可以转到正确的视图,但是我需要相同的功能才能工作,而无需单击下面显示 decode 的 http 响应。 status == 1 因为用户已成功验证。

struct ContentView: View 
    @State var email: String = ""
    @State var password: String = ""
    @State var message: String = ""
    @State var status: Int = -10
    @State var showActive = true
 
    var body: some View 

        NavigationView 
        ZStack 
            
           Color(UIColor.systemGroupedBackground)
            .edgesIgnoringSafeArea(.all)
            
           
        VStack(alignment: .center) 
      
            Spacer()
            
            NavigationLink(destination: MainView()) 
               Text("Press on me")
            .buttonStyle(PlainButtonStyle()) // This works when clicked
            
            TextField("Email", text: $email)
                .padding(10)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .background(Color(UIColor(hexString: ForestGreen)))
                .foregroundColor(Color.black)
            
            SecureField("Password", text: $password)
                .padding(10)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .background(Color(UIColor(hexString: ForestGreen)))
                .foregroundColor(Color.black)

             
            Button(action: 
                guard  let url = URL(string:ConnectionString+"profile/login") else  return 
                let parameter = "email=\(self.email)&password=\(self.password)"
                let request = RequestObject(AddToken: true, Url: url, Parameter: parameter)
                
                URLSession.shared.dataTask(with:request, completionHandler: (data, response, error) in
                    if let decode = try? JSONDecoder().decode(ProfileCodable.self, from: data!)
                    
                        self.status = decode.status ?? -10
                        self.message = decode.message ?? ""
                        if decode.status == 0 
                            print("Invalid Credentials")
                         else if decode.status == 1 
                
                           // ** Go to next View here **
                            
                         else if decode.status == -1 
                            print("Error")
                        
                        
                     else 
                         print("No Response")
                    
                    
                ).resume()
                
            ) 
                Text("Login")
                    .padding(10)
                    .frame(minWidth: 0, maxWidth: .infinity)
                    .font(.system(size: 22))
                    .foregroundColor(Color(UIColor(hexString: "#006622")))
                    .overlay(
                    RoundedRectangle(cornerRadius: 40)
                        .stroke(Color.black, lineWidth: 1))
           
                
            .padding([.top],40)
             

            if self.status == 0 
                Text(self.message)
                .foregroundColor(.red)
                .font(.system(size: 20))
                .padding([.top],30)
            
            
            
            Spacer()
        .padding()

        
     
    

【问题讨论】:

这能回答你的问题吗? SwiftUI NavigationLink: Navigate to a destination view AFTER running account creation code successfully 【参考方案1】:

试试这个(scratchy - 未测试,因为由于缺少依赖项而无法编译),所以在你身边适应:

struct ContentView: View 
    @State var email: String = ""
    @State var password: String = ""
    @State var message: String = ""
    @State var status: Int = -10
    @State var showActive = false      // << seems this state, so false
 
    var body: some View 

        NavigationView 
        ZStack 
            
           Color(UIColor.systemGroupedBackground)
            .edgesIgnoringSafeArea(.all)
            
           
        VStack(alignment: .center) 
      
            Spacer()
            
            TextField("Email", text: $email)
                .padding(10)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .background(Color(UIColor(hexString: ForestGreen)))
                .foregroundColor(Color.black)
            
            SecureField("Password", text: $password)
                .padding(10)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .background(Color(UIColor(hexString: ForestGreen)))
                .foregroundColor(Color.black)

             
            Button(action: 
                guard  let url = URL(string:ConnectionString+"profile/login") else  return 
                let parameter = "email=\(self.email)&password=\(self.password)"
                let request = RequestObject(AddToken: true, Url: url, Parameter: parameter)
                
                URLSession.shared.dataTask(with:request, completionHandler: (data, response, error) in
                    if let decode = try? JSONDecoder().decode(ProfileCodable.self, from: data!)
                    
                        self.status = decode.status ?? -10
                        self.message = decode.message ?? ""
                        if decode.status == 0 
                            print("Invalid Credentials")
                         else if decode.status == 1 
                
                           self.showActive = true             // << here !!
                            
                         else if decode.status == -1 
                            print("Error")
                        
                        
                     else 
                         print("No Response")
                    
                    
                ).resume()
                
            ) 
                Text("Login")
                    .padding(10)
                    .frame(minWidth: 0, maxWidth: .infinity)
                    .font(.system(size: 22))
                    .foregroundColor(Color(UIColor(hexString: "#006622")))
                    .overlay(
                    RoundedRectangle(cornerRadius: 40)
                        .stroke(Color.black, lineWidth: 1))
           
                
            .padding([.top],40)
            .background(
               // activated by state programmatically !!
               NavigationLink(destination: MainView(), isActive: $self.showActive) 
                  EmptyView()     // << just hide
               .buttonStyle(PlainButtonStyle())
            )


            if self.status == 0 
                Text(self.message)
                .foregroundColor(.red)
                .font(.system(size: 20))
                .padding([.top],30)
            
            
            
            Spacer()
        .padding()

        
     
    

【讨论】:

【参考方案2】:

只需使用导航链接的 isActive 属性。它看起来像这样:

NavigationLink(destination: MainView(), isActive: $mainViewActive) 
     Text("Press on me")
.buttonStyle(PlainButtonStyle()) 

您还应该在视图中声明该变量:

@State var mainViewActive = false

然后在成功登录时只需将值更改为 true。如果您也不想显示实际链接,请使用 EmptyView() 作为包装器。所以它看起来像这样:

NavigationLink(destination: MainView(), isActive: $mainViewActive) 
     EmptyView()

【讨论】:

以上是关于SwiftUI 成功后自动转到下一个视图的主要内容,如果未能解决你的问题,请参考以下文章

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

如何在 SwiftUI 中启动应用程序时有条件地加载视图?

使用 SwiftUI 成功登录后导航

在转到下一个视图控制器(Swift)之前进行异步调用

SwiftUI - 倒计时结束后,跳转到另一个视图

停止重复 SwiftUI 的动作的方法