[英]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:需要考虑的一些事项:
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.