使用 swiftui 和 rest api 構建新應用程式的 iOS 應用程式構建新手。在經歷了許多artilces等之后為登錄螢屏寫了這個
簽到類
import Foundation
enum AuthenticationError: Error{
case invalidCredentials
case custom(errorMessage : String)
}
class SignIn {
struct LoginRequest : Codable
{
let UserName : String
let Password : String
}
struct LoginResponse : Codable
{
let AuthToken : String?
let Message : String?
let IsSuccess : Bool?
}
func SignInUser(UserName : String, Password : String, completion : @escaping (Result<String,
AuthenticationError>)->Void)
{
guard let url = URL(string: "http://xx.xxx.xxx.x:port/api/home/login")
else
{
completion(.failure(.custom(errorMessage: "Invalid URL")))
return
}
let body = LoginRequest (UserName: UserName, Password: Password)
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Accept")
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
let encodeData = try? JSONEncoder().encode(body)
print(String(data: encodeData!, encoding: .utf8)!)
request.httpBody = encodeData
URLSession.shared.dataTask(with: request) {(data, response, error) in
guard let data = data , error == nil else
{
completion(.failure(.custom(errorMessage: "No Data")))
return
}
guard let loginResponse = try? JSONDecoder().decode(LoginResponse.self, from: data)
else
{
completion(.failure(.invalidCredentials))
return
}
guard let token = loginResponse.AuthToken else
{
completion(.failure(.invalidCredentials))
return
}
completion(.success(token))
}.resume()
}
}
登錄視圖模型
import Foundation
class SignInViewModel : ObservableObject {
@Published var username : String = ""
@Published var password : String = ""
func LogIn()
{
SignIn().SignInUser(UserName: username, Password: password)
{ **Line:#17**
result in
switch result{
case .success(let token):
print(token)
case .failure(let error):
print(error.localizedDescription)
}
}
}
}
SignInActivity
import SwiftUI
struct SignInActivity: View {
@StateObject private var loginVM = SignInViewModel()
@State private var Username:String = ""
@State private var Password:String = ""
var body: some View {
VStack(){
Image("logo").resizable().aspectRatio(contentMode:.fit)
Spacer()
Text("Welcome! Sign In to Continue ")
.font(.system(size: 20)).fontWeight(.semibold)
.foregroundColor(Color.blue)
Spacer()
VStack(){
HStack(alignment: .center){
Image(systemName: "person.circle.fill")
.foregroundColor(Color.blue)
.padding(.leading,8)
TextField(
"username", text:$loginVM.username)
.font(.system(size: 14))
.padding(.top,10)
.padding(.bottom,10)
// .overlay(VStack{
// Divider().offset(x:0,y:15)
// })
}.background(Color("text_bg"))
.cornerRadius(10)
.padding(.trailing,25)
.padding(.leading,25)
.padding(.bottom,15)
.textInputAutocapitalization(.never)
.disableAutocorrection(true)
HStack(alignment: .center)
{
Image(systemName: "lock.circle.fill")
.foregroundColor(Color.green)
.padding(.leading,8)
TextField(
"password", text:$loginVM.password
).font(.system(size: 14))
.padding(.top,10)
.padding(.bottom,10)
// .overlay(VStack{
// Divider().offset(x:0,y:15)
// })
}.background(Color("text_bg"))
.cornerRadius(10)
.padding(.trailing,25)
.padding(.leading,25)
.textInputAutocapitalization(.never)
.disableAutocorrection(true)
}
HStack()
{
Button(action: {
loginVM.LogIn()
})
{
Text("Sign In")
.padding(7)
.font(Font.system(size: 15))
.foregroundColor(.white).background(Color.green).cornerRadius(6).shadow(radius: 5)
}
}.padding(.top)
Spacer()
Spacer()
}.ignoresSafeArea(.keyboard)
}
該 API 運行良好,因為我已經在 android(已發布)中制作了完整的應用程式并且運行良好。現在嘗試為 iOS 制作應用程式。
在除錯時,錯誤是
completion () 0x0000000106b27820 ScreenLearning`closure #1 (Swift.Result<Swift.String,
ScreenLearning.AuthenticationError>) -> () in ScreenLearning.SignInViewModel.LogIn() -> () at
SignInViewModel.swift:17
運行時錯誤為 AutheticationError 1。
無法弄清楚發生了什么。
uj5u.com熱心網友回復:
要進行基本身份驗證,請嘗試使用以下方法,而不是在請求正文中不安全地將用戶和密碼作為 json 發送。(注:用戶名和密碼小寫)
func SignInUser(userName : String, password : String, completion : @escaping (Result<String, AuthenticationError>)->Void) {
// -- here
guard !userName.isEmpty && !password.isEmpty else {
completion(.failure(.custom(errorMessage: "Invalid userName or password")))
return
}
// -- here should use https
guard let url = URL(string: "http://xx.xxx.xxx.x:port/api/home/login")
else {
completion(.failure(.custom(errorMessage: "Invalid URL")))
return
}
// -- here
let hash = "\(userName):\(password)".data(using: .utf8)!.base64EncodedString()
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Accept")
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
// -- here
request.addValue("Basic \(hash)", forHTTPHeaderField: "Authorization")
URLSession.shared.dataTask(with: request) {(data, response, error) in
guard let data = data , error == nil else{
completion(.failure(.custom(errorMessage: "No Data")))
return
}
guard let loginResponse = try? JSONDecoder().decode(LoginResponse.self, from: data)
else {
completion(.failure(.invalidCredentials))
return
}
// -- here
guard let token = loginResponse.ResponseData?.AuthToken else {
completion(.failure(.invalidCredentials))
return
}
completion(.success(token))
}.resume()
}
注意:您正在使用http而不是所需的https. 在您https的.NSAppTransportSecurityInfo.plist
編輯:
注意,根據回應資料,你應該有這個模型:
struct ResponseData: Codable {
let AuthToken: String?
// ....
}
struct LoginResponse: Codable {
let Message: String?
let IsSuccess: Bool?
let ResponseData: ResponseData?
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/443628.html
