【问题标题】:Parsing JSON in Swift 5 with Generics - local files versus URL [duplicate]在 Swift 5 中使用泛型解析 JSON - 本地文件与 URL [重复]
【发布时间】:2021-01-09 06:32:46
【问题描述】:

我有以下两个函数用于帮助在 Swift 中解析 JSON。第一个函数可以很好地与我扔给它的任何 JSON 配合使用。

第二种方法让我很适应,但我无法弄清楚问题所在。我本质上想做与第一个函数相同的事情,但我的数据来自 URLSession 而不是本地文件。

任何想法我在这里做错了什么?我得到一个奇怪的编译器错误,Unexpected non-void return value in void function,但签名完全相同。

import Foundation
import SwiftUI


// Populates Model from local files
public func loadFromJson<T: Decodable>(_ filename: String) -> T {
    let data: Data
    
    guard let path = Bundle.main.path(forResource: filename, ofType: "json")
   
    else{
        fatalError("\(filename) not found.")
    }
    do {
        let file = URL(fileURLWithPath: path)
        data = try Data(contentsOf: file)
    } catch {
        fatalError("Could not load \(filename): (error)")
    }
    
    do{
        return try JSONDecoder().decode(T.self, from: data)
    } catch {
        fatalError("Unable to parse \(filename): (error)")
    }
}

// Populates Model from REST endpoint
public func loadFromJsonFromURL<T: Decodable>(_ urlString: String) -> T {
    let data: Data
    
    let url = URL(string: urlString)!

    let task = URLSession.shared.dataTask(with: url) { data, response, error in
        
        if let error = error {
            fatalError("Error: \(error.localizedDescription)")
        }
        
        
        guard let response = response as? HTTPURLResponse, response.statusCode == 200 else {
            fatalError("Error: invalid HTTP response code")
        }
        
        guard let data = data else {
            fatalError("Error: missing response data")
        }

        do {
            return try JSONDecoder().decode(T.self, from: data)
        }
        catch {
            print("Error: \(error.localizedDescription)")
        }
    }
    task.resume()
    
}

【问题讨论】:

    标签: json swift generics urlsession


    【解决方案1】:

    dataTask(with: completionHandler:) 是一个 async 方法。所以,直到收到响应后调用completionHandler,方法loadFromJsonFromURL(_:_:)已经返回。

    在收到 API 的响应后,您需要使用 closure 将数据传回。

    public func loadFromJsonFromURL<T: Decodable>(_ urlString: String, _ handler: @escaping ((T?)->())) {
        if let url = URL(string: urlString) {
            let task = URLSession.shared.dataTask(with: url) { data, response, error in
                if let error = error {
                    fatalError("Error: \(error.localizedDescription)")
                }
                guard let response = response as? HTTPURLResponse, response.statusCode == 200 else {
                    fatalError("Error: invalid HTTP response code")
                }
                guard let data = data else {
                    fatalError("Error: missing response data")
                }
                do {
                    let value = try JSONDecoder().decode(T.self, from: data)
                    handler(value)
                }
                catch {
                    print("Error: \(error.localizedDescription)")
                    handler(nil)
                }
            }
            task.resume()
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-07-14
      • 2012-11-19
      • 1970-01-01
      • 1970-01-01
      • 2013-02-28
      • 2020-06-22
      • 1970-01-01
      • 2011-12-05
      相关资源
      最近更新 更多