简体   繁体   English

成功 http 请求登录后直接到 swiftUI 中的新视图

[英]direct to new view in swiftUI after successful http request login

I've been using php and a mysql database to create a simple user registration and login system.我一直在使用 php 和 mysql 数据库来创建一个简单的用户注册和登录系统。 the login php files work, and I have connected it to my project in Xcode.登录 php 文件有效,我已将其连接到 Xcode 中的项目。 however, I'm not too sure on how to make sure that this function runs when the login button is clicked, and only moves to the next view when the log in has been successful.但是,我不太确定如何确保这个 function 在单击登录按钮时运行,并且只有在登录成功后才会移动到下一个视图。

This is my swift code:这是我的 swift 代码:

import SwiftUI


struct loginview_Previews: PreviewProvider {
static var previews: some View {
    loginview()
}
}

struct loginview: View {

// variables and fields

@State private var username : String  = ""
@State private var password : String = ""

let databaseurl = "http://localhost/login.php"

var body: some View {
        
        // put into a navigation view
        
        NavigationView{
            
            // form to enter details
            
            Form{
                
                // start section with a header for info
                
                Section(header: Text("enter your details to log in !")){
                    
                    // username field
                    
                    TextField("username", text: $username)
                        
                        .font(.headline)
                        .frame(width: 350.0)
                        .foregroundColor(.white)
                        .padding(.all, 20.0)
                        .cornerRadius(9.0)
                        .preferredColorScheme(.dark)
                    
                    TextField("password", text: $password)
                        
                        .font(.headline)
                        .frame(width: 350.0)
                        .foregroundColor(.white)
                        .padding(.all, 20.0)
                        .cornerRadius(9.0)
                        .preferredColorScheme(.dark)
                    
                } .textCase(nil)  // make header lowercase
                
                Section{
                    NavigationLink(destination: homepage()){  // link to home page view
                        
                        Text("submit")
                            
                            .foregroundColor(.white)
                            .fontWeight(.heavy)
                            .font(.system(size: 22))
                            .padding(.all, 20.0)
                            .frame(width: 175.0)
                            .preferredColorScheme(.dark)
                        
                    }
                }
                
                // button is unclickable if textfields are empty
                
                .disabled(username.isEmpty)
                .disabled(password.isEmpty)
            }
            
            .navigationBarTitle("log in") // title of form
        }
    }

//

func logindatabase(){
            
            // create NSURL - an object initialized with URLString
            
            if var requesturl = URLComponents(string: databaseurl) {
                
                requesturl.query = "username=\(username)&password=\(password)"
                print(requesturl)
                
                guard let url = requesturl.url else { return }
                
                let task = URLSession.shared.dataTask(with: url) { data, response, error in

                    
                    if error != nil {
                        print("error is \(String(describing: error))")
                        return
                    }
                    
                    // parse the response
                    
                    do {
                        // convert response to NSDictionary
                        
                        let myJSON = try JSONSerialization.jsonObject(with: data! , options: .mutableContainers) as? NSDictionary
                        
                        if let parseJSON = myJSON {
                            // create a string & get the json response
                            
                            guard let message = parseJSON["message"] as? String else { return }
                            
                            // print the response
                            
                            print(message)
                            
                        }
                        
                    } catch {
                        print(error)
                    }
                }
                task.resume()
            }

        }
 }

and this is my login.php file:这是我的 login.php 文件:

<?php

//include the db operation file
require_once 'dboperations.php' ;

// create a response array
$response = array();

if ($_SERVER['REQUEST_METHOD'] == 'GET') {

    if (isset($_GET['username']) && isset($_GET['password'])) {

        $db = new dboperation();

        if ($db->userlogin($_GET['username'], $_GET['password'])) {
            $response['error'] = false;
            $response['user'] = $db->displayuser($_GET['username']);
        } else {
            $response['error'] = true;
            $response['message'] = 'invalid username or password';
        }

    } else {
        $response['error'] = true;
        $response['message'] = 'parameters are missing';
    }

} else {
    $response['error'] = true;
    $response['message'] = "Request not allowed";
}

echo json_encode($response);

which does work successfully.这确实有效。

Here's a very simple version of what you're talking about:这是您正在谈论的一个非常简单的版本:

class LoginManager : ObservableObject {
    @Published var isLoggedIn = false
    
    func doLogin(username: String, password: String) {
        //in here, you'll do your network call
        //I've mocked it with a simple async call for now
        DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
            //set this once you get the correct response from your server
            //this triggers isActive on the NavigationLink below
            self.isLoggedIn = true
        }
    }
}

struct ContentView : View {
    @ObservedObject private var loginManager = LoginManager()
    
    @State var username = ""
    @State var password = ""
    
    var body: some View {
        NavigationView {
            Button(action: {
                loginManager.doLogin(username: username, password: password)
            }) {
                //Login fields...
                Text("Log me in")
            }.overlay(
                NavigationLink(destination: LoggedInView(), isActive: $loginManager.isLoggedIn) {
                    EmptyView()
                }
            )
        }
    }
}

struct LoggedInView : View {
    var body: some View {
        Text("Logged in")
    }
}

Note that instead of a NavigationLink I'm using a Button for the initial action.请注意,我使用Button来代替NavigationLink进行初始操作。 Then, that calls a function called doLogin which is a @Published property saying whether the user is logged in.然后,调用一个名为doLogin的 function,它是一个 @Published 属性,表示用户是否已登录。

If isLoggedIn is true, isActive on the NavigationLink is triggered, sending the user to the next view.如果isLoggedIn为真,则触发NavigationLink上的isActive ,将用户发送到下一个视图。

Some things to consider:需要考虑的一些事项:

  1. In the real world, you should never be sending usernames/passwords over a GET request -- it's just too insecure在现实世界中,您永远不应该通过 GET 请求发送用户名/密码——这太不安全了
  2. In the event that you don't want the user to just be able to use the Back button to go back to the initial login screen, you may not actually wan to use NavigationLink at all -- you might just want to conditionally display a view:如果您不希望用户只能使用Back按钮 go 返回初始登录屏幕,您可能根本不想使用NavigationLink - 您可能只想有条件地显示一个视图:
if loginManager.isLoggedIn {
  LoggedInView()
} else {
  LoginForm()
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM