Swift - 将 json 数据传递给其他视图 [英] Swift - Pass json data to other views
问题描述
我想弄清楚如何传递从成功结果中接收到的 json 解码数据,以便我可以开始使用它在另一个屏幕视图上显示特定信息.我一直试图在没有运气的情况下弄清楚,我是 swift 和应用程序开发的新手,所以这对我来说都是一次学习经历.如果有人可以提供帮助,将不胜感激.这是我的一些网络代码
Im trying to figure out how I could pass my json decoded data that I receive from a successful Result so I can start using it to display specific info on another screen view. Iv been trying to figure it out with no luck, Im new to swift as well as app development so this is all a learning experience for me. If anyone can help that would be much appreciated. This is some of my network code
func request<T: Decodable>(endPoint: EndPoint, method: Method, parameters: [String: Any]? = nil, completion: @escaping(Result<T, Error>) -> Void) {
// Creates a urlRequest
guard let request = createRequest(endPoint: endPoint, method: method, parameters: parameters) else {
completion(.failure(AppError.invalidUrl))
return
}
let session = URLSession.shared
session.dataTask(with: request) { data, response, error in
var results: Result<Data, Error>?
guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else {
completion(.failure(AppError.badStatusCode))
return
}
if let response = response {
// Gets the JSESSIONID
let cookieName = "JSESSIONID"
if let cookie = HTTPCookieStorage.shared.cookies?.first(where: { $0.name == cookieName }) {
debugPrint("\(cookieName): \(cookie.value)")
}
print(response)
}
// Look into this
if let data = data {
results = .success(data)
/*
// Converts data to readable String
let responseString = String(data: data, encoding: .utf8) ?? "unable to convert to readable String"
print("Server Response: \(responseString.description)")
*/
} else if let error = error {
print("NO this happen")
results = .failure(error)
print("Server Error: \(error.localizedDescription)")
}
DispatchQueue.main.sync {
self.handleResponse(result: results, completion: completion)
}
}.resume()
}
private func handleResponse<T: Decodable>(result: Result<Data, Error>?, completion: (Result<T, Error>) -> Void) {
guard let result = result else {
completion(.failure(AppError.unknownError))
return
}
switch result {
case .success(let data):
/*
do {
let json = try JSONSerialization.jsonObject(with: data, options: [])
print("Server JsonObject response: \(json)")
} catch {
completion(.failure(AppError.errorDecoding))
}*/
let decoder = JSONDecoder()
// Decodes that json data
do {
let json = try decoder.decode(T.self, from: data)
completion(.success(json))
} catch {
completion(.failure(error))
}
case .failure(let error):
print("This happen")
completion(.failure(error))
}
}
这是我用来创建请求的函数
This is the function I use to create my request
func signIn(username: String, password: Any, completion: @escaping(Result<LoginResponseData.Root, Error>) -> Void) {
let params = ["username": "\(username)", "password": "\(password)"]
request(endPoint: .Login, method: .post, parameters: params, completion: completion)
}
这是我的登录查看代码
struct SignIn: View {
@Binding var userID: String
@Binding var passcode: String
@State private var showAlert = false
@EnvironmentObject var authentication: AuthenticationCheck
var body: some View {
Button(action: {
// Remove
print("Button action")
NetworkService.shared.signIn(username: userID, password: passcode) { (result) in
switch result {
case .success(let user):
print("This user last name is: \(user.result.login.userName.name.fullName)")
authentication.updateValidation(success: true)
showAlert = false
case .failure(let error):
print("The error is: \(error.localizedDescription)")
showAlert.toggle()
}
}
}) {
Text("Sign In")
.multilineTextAlignment(.center)
.padding()
}
.frame(width: 150.0, height: 43.0)
.background(/*@START_MENU_TOKEN@*//*@PLACEHOLDER=View@*/Color(red: 0.584, green: 0.655, blue: 0.992)/*@END_MENU_TOKEN@*/)
.foregroundColor(.white)
.cornerRadius(20)
.disabled(userID.isEmpty || passcode.isEmpty)
.alert(isPresented: $showAlert, content: {
Alert(title: Text("Invalid Credentials"), message: Text("Either username or password is incorrect. Please try again"), dismissButton: .cancel())
})
}
这是我的身份验证检查 &应用
This is my authentification check & App
class AuthenticationCheck: ObservableObject {
@Published var isValidated = false
func updateValidation(success: Bool) {
withAnimation {
isValidated = success
}
}
}
@main
struct SomeApp: App {
@StateObject var authenticationCheck = AuthenticationCheck()
var body: some Scene {
WindowGroup {
if authenticationCheck.isValidated {
ContentView()
.environmentObject(authenticationCheck)
} else {
Signin()
.environmentObject(authenticationCheck)
}
//TestView()
}
}
}
推荐答案
这是您的代码的简化版本
Here is a simplified version of your code
class AuthViewModel: ObservableObject {
// I don't have your Model info
//You can have an empty object of your model or you can make it an optional, etc
@Published var user: YourModel? = nil
@Published var alert: CustomAlert? = nil
let networkService: NetworkService = NetworkService.shared
var authentication: AuthenticationCheck? = nil
func signIn(username: String, password: String) {
networkService.signIn(username: username, password: password){ (result) in
switch result {
case .success(let user):
print("This user last name is: \(user)")
//Assign you value to the Published variable here
self.user = user
self.authentication?.updateValidation(success: true)
self.alert = CustomAlert(title: "Success", message: "You logged in")
case .failure(let error):
print("The error is: \(error)")
//Reset the variable
self.user = nil
self.authentication?.updateValidation(success: false)
//You can pass a better message to the user like this
self.alert = CustomAlert(title: "Invalid Credentials", message: "\(error)")
}
}
}
func logout() {
self.user = nil
authentication?.updateValidation(success: false)
self.alert = CustomAlert(title: "See you later", message: "You logged out")
}
}
class AuthenticationCheck: ObservableObject {
@Published var isValidated = false
func updateValidation(success: Bool) {
withAnimation {
isValidated = success
}
}
}
struct SampleNetworkView: View {
@StateObject var vm: AuthViewModel = AuthViewModel()
@StateObject var authentication: AuthenticationCheck = AuthenticationCheck()
@State var username: String = ""
@State var password: String = ""
var body: some View {
NavigationView{
switch authentication.isValidated{
case true:
VStack{
Text("Signed In - you are now in the content view")
.toolbar(content: {
Button("log out", action: {
vm.logout()
})
})
}
case false:
VStack{
TextField("username", text: $username).textFieldStyle(RoundedBorderTextFieldStyle())
SecureField("password", text: $password).textFieldStyle(RoundedBorderTextFieldStyle())
Button("sign in", action: {
vm.signIn(username: username, password: password)
}).disabled(username.isEmpty || password.isEmpty)
}
}
}
//Inject the StateObjects to the navigation view so you can access the variables
.environmentObject(authentication)
.environmentObject(vm)
//Create a shared Alert for the ViewModel
.alert(item: $vm.alert, content: { customAlert in
Alert(title: Text(customAlert.title), message: Text(customAlert.message), dismissButton: .default(Text("ok")))
})
//Pass the authentication to the ViewModel so you can pass info
.onAppear(perform: {
vm.authentication = authentication
})
}
}
struct SampleNetworkView_Previews: PreviewProvider {
static var previews: some View {
SampleNetworkView()
}
}
//This assists in creating a shared alert
struct CustomAlert : Identifiable {
let id: UUID = UUID()
var title: String
var message: String
}
这篇关于Swift - 将 json 数据传递给其他视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!