当前位置: 首页 > 知识库问答 >
问题:

从SwiftUI Xcode中的JSON API响应获取值

松刚豪
2023-03-14

我需要发布一个https请求到登录视图(SwiftUI),我的代码遵循getres中的代码。斯威夫特:所以我需要从回应中获得价值,并把它写进文本中

      import Foundation
        import Combine

        struct result: Decodable {
           let res, ordercount, rate: String
        }

        class getres: ObservableObject {

          let objectWillChange = PassthroughSubject<getres, Never>()
        @Published var authenticated = ""
          @Published var todos = [result]() {
              didSet {
                   objectWillChange.send(self)
              }
           }

            func auth(username: String, password: String) {
            guard let url = URL(string: "http://company.com/auth.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 fineldata=try! JSONDecoder().decode(result.self, from: data)


        DispatchQueue.main.async {
            self.todos = [fineldata]
            self.authenticated=fineldata.res


        }


 print(fineldata)









    }.resume()
          }

        }

在登录页面中,我尝试显示其他视图

在这段代码中,我将从函数中获取值,作为json响应,我将获取ordercount,并将其放在另一个视图中

 import SwiftUI

    struct ContentView: View {

    @State private var username: String = ""
    @State private var password: String = ""

    @ObservedObject   var manager = getres()


    var body: some View {

        VStack(alignment: .leading) {

            if manager.authenticated == "2"{
                                        userdetails()
                                    }else{


            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.auth(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()
        }
       }

在userdetails中,我需要从响应中获取值

struct userdetails: View {

  @State var controller = getres()
    var body : some View{
        ScrollView(Axis.Set.vertical, showsIndicators: true) {

            VStack(spacing: 20){
            Image("wlogo").renderingMode(.original);              HStack(spacing: 15){

                  Spacer()
                  VStack(alignment: .center, spacing: 10) {

                    Text(???).foregroundColor(Color.white).bold()
                        .font(.largeTitle)

                    Text("")
                    .foregroundColor(Color.white)
                        .font(.headline)                  }

                  Spacer()
              }}}}

如何从响应中获取ordercount并输入文本(???)在视图中,查看示例控制器的userdetails。待办事项。ordercount在尝试文本(controller.todos.ordercount)json响应时,我得到类型为“[result]”的错误值没有成员“ordercount”

{"res":"2","ordercount":"20","rate":"5"}

共有1个答案

洪国兴
2023-03-14

最新答案

1.)如果您只将代码复制到一个部分,这会很有帮助-这对我们所有人来说都更容易复制2。)在手动复制或更改代码中的某些内容之前,您应该自己尝试代码。发现以下错误很烦人:

如果manager.authenticated=="2"{用户详细信息()}其他{

        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.auth(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()}

}

在这里,您将. padd()添加到if-语句......

3.)你应该用这样的方式命名类名:人们可以理解类的用途,并以大写字母开头,就像Apple对所有类名所做的那样

)你也应该开始查看大写的名称(像苹果一样)5。)因为我必须访问你的页面,你没有提供示例数据和/或密码,我不知道有什么数据...

以下是迄今为止我的解决方案代码:

我添加了一些伪造数据,因为我无法访问您的数据。。。。所以你可以看到一些细节。

struct ToDo: Decodable, Identifiable {

    var id = UUID().uuidString

    let res, ordercount, rate: String
}

class ToDoGetter: ObservableObject {

    let objectWillChange = PassthroughSubject<ToDoGetter, Never>()
    @Published var authenticated = ""
    @Published var todos = [ToDo]() {
        didSet {
            objectWillChange.send(self)
        }
    }

    let someFakingTodos = [
        ToDo(res: "a", ordercount: "5", rate: "75%"),
        ToDo(res: "b", ordercount: "52", rate: "5%"),
        ToDo(res: "c", ordercount: "566", rate: "7%"),
        ToDo(res: "d", ordercount: "53", rate: "33%"),
        ToDo(res: "e", ordercount: "15", rate: "44%"),
        ToDo(res: "f", ordercount: "345", rate: "10%")

    ]

    func auth(username: String, password: String) {
        guard let url = URL(string: "http://company.com/auth.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 fineldata=try! JSONDecoder().decode(ToDo.self, from: data)

            DispatchQueue.main.async {
                self.todos = [fineldata]
                self.authenticated=fineldata.res
            }
            print(fineldata)
        }.resume()
    }
}

struct ContentView: View {

    @EnvironmentObject var todoGetter : ToDoGetter

    @State private var username: String = ""
    @State private var password: String = ""


    @State var navigateToDetail : Bool = false

    var body: some View {
        NavigationView {
            VStack(alignment: .leading) {

                if todoGetter.authenticated == "2"{
                    Userdetails().environmentObject(todoGetter)
                } else{

                    Text("Username")
                    TextField("placeholder", text: $username)
                        .textFieldStyle(RoundedBorderTextFieldStyle())
                        .border(Color.green)
                        .autocapitalization(.none)

                    Text("Password")
                    SecureField("placeholder", text: $password)
                        .textFieldStyle(RoundedBorderTextFieldStyle())
                        .border(Color.green)

                    NavigationLink(destination: Userdetails(), isActive: self.$navigateToDetail) {
                        EmptyView() }
                        .hidden()
                        .padding()

                    Button(action: {

                        self.todoGetter.auth(username: self.username, password: self.password)
                        self.navigateToDetail.toggle()
                    }) {
                        HStack{
                            Spacer()
                            Text("Login")
                            Spacer()
                        }
                        .accentColor(Color.white)
                        .padding(.vertical, 10)
                        .background(Color.red)
                        .cornerRadius(5)
                        .padding(.horizontal, 40)
                    }
                }
            }
        }
    }
}

struct Userdetails: View {

    @EnvironmentObject var todoGetter : ToDoGetter

    var body : some View{

        VStack(spacing: 20) {
            Image("wlogo").renderingMode(.original);              HStack(spacing: 15){

                Spacer()

                List(todoGetter.someFakingTodos) { todo in

                    VStack(alignment: .center, spacing: 10) {
                        HStack {
                            Text(todo.res).foregroundColor(Color.white).bold()
                                .font(.largeTitle)

                            Text(todo.ordercount)
                                .foregroundColor(Color.white)
                                .font(.headline)
                            Text(todo.rate)
                                .foregroundColor(Color.white)
                                .font(.headline)
                        }
                    }.background(Color.black)

                    Spacer()
                }
            }
        }
    }
}

旧答案

你调用getres 2次.你必须调用它只有一次,然后给值的细节视图。

每个应用程序只能创建一次模型。

 类似资料:
  • 我已经使用API从API中提取了JSON响应,请放心,它看起来像这样: 现在,我实际的JSON响应在JSON数组中有数千个JSON对象,一些键有空值,例如“secondKey”在一些JSON对象中有空值。我需要获取JSON响应中所有空值的键。对我该如何做有什么想法吗? 我解决这个问题的想法是使用Jackson库反序列化JSON并获取所有空值。然而,考虑到性能,是否有任何有效的解决方案?

  • 如何从json响应中获取键“存在”的值?我之前试过 但它不起作用。如果我print_r回应,这就是正在打印的内容: 我当前的代码:

  • 我有一个关于从JMeter中的html响应数据中获取某个值的问题。我一直在尝试正则表达式和xpath提取器(见下文),但没有运气。 但也不管用。我一直在考虑使用Beanshell将源代码抓取为字符串并解析数字。有什么更好的方法来抢那个号码吗?如何使用beanshell获取响应数据的源代码?我尝试使用/html的xpath,但没有成功。 多谢

  • 问题内容: 我在同一个域上有一个请求,我想读取cookie。它不断返回。 有任何想法吗?我为此使用Chrome。 问题答案: 您正在寻找的响应标头: 它不适用于HTTPOnly cookie。 更新资料 根据XMLHttpRequest级别1和XMLHttpRequest级别2,此特定的响应标头属于您可以使用所获得的“禁止”响应标头,因此,该方法可以起作用的唯一原因基本上是一个“顽皮的”浏览器。

  • 我用邮递员寄出这个请求https://postman-echo.com/get?record=aaaa 测试包含以下代码: 控制台中的输出: 对象对象 我所期待的:回应json {“args”:{“record”:“aaaa”},“headers”:{“x-forwarded-proto”:“https”,“x-forwarded-port”:“443”,“host”:“postman echo.