Ios 成功登录http请求后直接在swiftUI中创建新视图
我一直在使用php和mysql数据库创建一个简单的用户注册和登录系统。登录php文件可以工作,我已经用Xcode将其连接到我的项目。但是,我不太确定如何确保在单击“登录”按钮时运行此函数,并且仅在登录成功后才移动到下一个视图 这是我的swift代码: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
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()
}