Swift - 将 json 数据传递给其他视图 [英] Swift - Pass json data to other views

查看:36
本文介绍了Swift - 将 json 数据传递给其他视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想弄清楚如何传递从成功结果中接收到的 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆