ログインビュー(SwiftUI)にhttpリクエストを投稿する必要があります。私のコードはHttpAuth.Swiftにあります。
import Foundation
import Combine
struct ServerMessage: Decodable {
let res, message: String
}
class HttpAuth: ObservableObject {
let objectWillChange = PassthroughSubject<HttpAuth, Never>()
var authenticated = false {
didSet {
objectWillChange.send(self)
}
}
func postAuth(username: String, password: String) {
guard let url = URL(string: "http://mysite/loginswift.php") else { return }
let body: [String: String] = ["username": username, "password": password]
let finalBody = try! JSONSerialization.data(withJSONObject: body)
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = finalBody
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
URLSession.shared.dataTask(with: request) { (data, response, error) in
guard let data = data else { return }
let resData = try! JSONDecoder().decode(ServerMessage.self, from: data)
print(resData.res)
if resData.res == "correct" {
DispatchQueue.main.async {
self.authenticated = true
}
}
}.resume()
}
}
そしてContentView.Swiftで:
import SwiftUI
struct ContentView: View {
@State private var username: String = ""
@State private var password: String = ""
@State var manager = HttpAuth()
var body: some View {
VStack(alignment: .leading) {
if self.manager.authenticated {
Text("Correct!").font(.headline)
}
Text("Username")
TextField("placeholder", text: $username)
.textFieldStyle(RoundedBorderTextFieldStyle())
.border(Color.green)
.autocapitalization(.none)
Text("Password")
SecureField("placeholder", text: $password)
.textFieldStyle(RoundedBorderTextFieldStyle())
.border(Color.green)
Button(action: {
self.manager.postAuth(username: self.username, password: self.password)
}) {
HStack{
Spacer()
Text("Login")
Spacer()
}
.accentColor(Color.white)
.padding(.vertical, 10)
.background(Color.red)
.cornerRadius(5)
.padding(.horizontal, 40)
}
}.padding()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
動作します。サーバーから回答を受け取りますが、ContentViewを更新しません。ContentViewの 'self.manager.authenticated'は、HttpAuthクラスから更新されません。
コードのこの部分は機能しません:
if self.manager.authenticated {
Text("Correct!").font(.headline)
}
「認証済み」はまだfalseです。
どうすれば修正できますか、ありがとうございます。
あなたはこれを試すことができます:
の代わりに
let objectWillChange = PassthroughSubject<HttpAuth, Never>()
var authenticated = false {
didSet {
objectWillChange.send(self)
}
}
使用する
@published var authenticated = false
代わりに
@State var manager = HttpAuth()
使用する
@EnvironmentObject private var manager: HttpAuth
そしてもちろん、ContentViewを呼び出すときにこれを行います。
ContentView().environmentObject(manager)
グローバル変数のようにクラスの外のどこか
var manager = HttpAuth()
その後、動作するはずです。
受け入れられた回答は目的を満たしていますが、@EnvironmentObject
およびビューの特定のリクエストではなく、アプリケーション全体の問題に使用する必要があります。
ビューに固有の「ViewModel」を実装して、リクエストの作業を行い、変数を更新できます。
ドキュメント: https://developer.Apple.com/documentation/combine/observableobject
@Chrisによって提案された変更に基づくと、コードの実装は次のようになります。
HttpAuth.swif:
import Foundation
import SwiftUI
import Combine
class HttpAuth: ObservableObject {
@Published var authenticated = false
func postAuth(username: String, password: String) {
guard let url = URL(string: "http://mysite/loginswift.php") else { return }
let body: [String: String] = ["username": username, "password": password]
let finalBody = try! JSONSerialization.data(withJSONObject: body)
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = finalBody
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
URLSession.shared.dataTask(with: request) { (data, response, error) in
guard let data = data else { return }
let resData = try! JSONDecoder().decode(ServerMessage.self, from: data)
print(resData.res)
if resData.res == "correct" {
DispatchQueue.main.async {
self.authenticated = true
}
}
}.resume()
}
}
ContentView.Swift
import SwiftUI
struct ContentView: View {
@State private var username: String = ""
@State private var password: String = ""
@ObservedObject var manager = HttpAuth()
var body: some View {
VStack(alignment: .leading) {
if self.manager.authenticated {
Text("Correct!").font(.headline)
}
Spacer()
Text("Username")
TextField("placeholder", text: $username)
.textFieldStyle(RoundedBorderTextFieldStyle())
.border(Color.green)
.autocapitalization(.none)
Text("Password")
SecureField("placeholder", text: $password)
.textFieldStyle(RoundedBorderTextFieldStyle())
.border(Color.green)
Button(action: {
self.manager.postAuth(username: self.username, password: self.password)
}) {
HStack{
Spacer()
Text("Login")
Spacer()
}
.accentColor(Color.white)
.padding(.vertical, 10)
.background(Color.red)
.cornerRadius(5)
.padding(.horizontal, 40)
}
Spacer()
}.padding()
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
}