Ios 成功登录http请求后直接在swiftUI中创建新视图

Ios 成功登录http请求后直接在swiftUI中创建新视图,ios,swiftui,swiftui-navigationlink,Ios,Swiftui,Swiftui Navigationlink,我一直在使用php和mysql数据库创建一个简单的用户注册和登录系统。登录php文件可以工作,我已经用Xcode将其连接到我的项目。但是,我不太确定如何确保在单击“登录”按钮时运行此函数,并且仅在登录成功后才移动到下一个视图 这是我的swift代码: import SwiftUI struct loginview_Previews: PreviewProvider { static var previews: some View { loginview() } } struct l

我一直在使用php和mysql数据库创建一个简单的用户注册和登录系统。登录php文件可以工作,我已经用Xcode将其连接到我的项目。但是,我不太确定如何确保在单击“登录”按钮时运行此函数,并且仅在登录成功后才移动到下一个视图

这是我的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()
            }

        }
 }
这是我的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);

以下是您所说内容的一个非常简单的版本:

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")
    }
}
请注意,我使用的不是
导航链接
,而是
按钮
进行初始操作。然后,调用名为
doLogin
的函数,该函数是@Published属性,表示用户是否登录

如果
isLoggedIn
为true,则会触发
NavigationLink
上的
isActive
,将用户发送到下一个视图

需要考虑的一些事项:

  • 在现实世界中,您永远不应该通过GET请求发送用户名/密码——这太不安全了
  • 如果您不希望用户仅能使用
    返回
    按钮返回初始登录屏幕,您可能根本不想使用
    导航链接
    ——您可能只想有条件地显示一个视图:

  • 非常感谢你!我对这一点很陌生,因此我不确定在我的代码中到底应该将self.isLoggedIn=true放在哪里,因为我不知道在哪里编码是否已从服务器收到正确的响应。您需要将
    logindabase
    函数移到
    LoginManager
    类中。然后,如果从服务器获得适当的响应,则可以设置
    isLoggedIn
    。现在,您正试图从JSON响应中打印“message”,但从服务器代码来看,如果登录正常,您实际上不会发送“message”字段。因此,您可以添加一个消息字段,或者改为检查“用户”字段。它终于起作用了,谢谢!它允许用户在详细信息正确时继续操作,而在不正确时不允许,但有一个小问题-当详细信息不正确时,它会进入主页,然后快速重定向回登录页面,我不确定为什么会这样做,这一定是您设置为isLoggedIn的某个地方的逻辑错误。如果你发布代码,我可以看看。我把它作为一个新问题发布,非常感谢你的帮助!
    if loginManager.isLoggedIn {
      LoggedInView()
    } else {
      LoginForm()
    }