【问题标题】:How to show parsed data with SwiftUI?如何使用 SwiftUI 显示解析的数据?
【发布时间】:2021-06-06 11:55:28
【问题描述】:

我正在尝试在视图中显示使用 SwiftUI 从 API 解析的数据。

我正在使用此代码正确获取数据:

import UIKit

class APIController: ObservableObject {
    
    func apiCall() {
        
        // URL
        let url = URL(string: "https://geek-jokes.p.rapidapi.com/api?format=json")
        
        guard url != nil else {
            print("Error creating url object")
            return
        }
        
        // URL Rquest
        var request = URLRequest(url: url!, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10)
        
        // Specify the header
        let headers = [
            "x-rapidapi-key": "d1363cbe66msh266920b6366eaacp1f87dfjsn050e3f8e58e2",
            "x-rapidapi-host": "geek-jokes.p.rapidapi.com"
        ]
        
        request.allHTTPHeaderFields = headers
        
        //     Specify the body
        //        let jsonObject = [
        //            "sign": "Aries"
        //        ] as [String:Any]
        //
        //        do {
        //        let requestBody = try JSONSerialization.data(withJSONObject: jsonObject, options: .fragmentsAllowed)
        //
        //            request.httpBody = requestBody
        //        }
        //        catch {
        //            print("Error creating the data object from json")
        //        }
        
        // Set the request type
        request.httpMethod = "GET"
        
        // Get the URLSession
        let session = URLSession.shared
        
        // Create the data task
        let dataTask = session.dataTask(with: request) { data, response, error in
            
            // Check for errors
            if error == nil && data != nil {
                
                //          Try to parse out the JSON data
                let decoder = JSONDecoder()
                
                do {
                    let jokesData = try decoder.decode(JokesData.self, from: data!)
                    
                    print(jokesData)
                }
                catch {
                    print("Error in JSON parsing")
                }
                
                //             Try to print out the JSON data
                //                do {
                //                    let dictionary = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? [String:Any]
                //                    print(dictionary)
                //
                //                }
                //                catch {
                //                    print("Error parsing response data")
                //                }
                
            }
        }
        
        // Fire off the data task
        dataTask.resume()
        
    }
    
}

那我不确定JokesData.swift中数据是否正确导入

import foundation

struct JokesData: Codable {

    var joke:String = ""

}

当我尝试在 JokesView.swift 中加载数据时,什么也没有出现:(

import SwiftUI

struct JokesView: View {

    var jokesData: JokesData

    @StateObject var viewRouter: ViewRouter

    var body: some View {
        Text(jokesData.joke)
            .foregroundColor(.black)
    }
}

如果有人知道我做错了什么,那将非常有帮助。

【问题讨论】:

  • 你必须把解码代码放到Observable类中,这可以是ViewRouter和@Publish jokesData
  • 将解析代码放在 ViewRouter 中,因为您在 JokesView 中观察到这一点。 ViewRouter 应该具有 Published 属性jokesData 或者如果有兴趣仅更新笑话并在 JokesView 中以 viewRouter.jokesData.joke 的形式访问它,则可能是笑话
  • @vadian 该死,我尝试了很多东西,但似乎没有任何效果。解码代码是指结构 JokesData?
  • @Apoorv 通过解析代码你的意思是 struct JokesData?
  • 我主要是指dataTask / JSONDecoder 的东西,结构可以在任何地方。

标签: api parsing swiftui


【解决方案1】:
  • APIController添加一个属性

    @Published var jokesData = JokesData() 
    
  • 将完成处理程序中的 do - catch 块替换为

      do {
          let jokesData = try decoder.decode(JokesData.self, from: data!)
    
          print(jokesData)
          DispatchQueue.main.async {
              self.jokesData = jokesData
          }
    
      }
      catch {
          print(error)
      }
    

    它将接收到的数据分配给发布jokesData属性。

  • 在视图中创建一个@StateObject的控制器,在onAppear修饰符中加载数据,视图会自动更新。

    import SwiftUI
    
    struct JokesView: View {
    
        @StateObject var apiController = APIController()
    
        var body: some View {
            Text(apiController.jokesData.joke)
                .foregroundColor(.black)
                .onAppear() {
                    apiController.apiCall()
                }
        }
    }
    

【讨论】:

  • 它有效,非常感谢@vadian!非常感谢。神圣的调度队列..
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多