gpt4 book ai didi

json - 如何在 Swift 中使用 OperationQueue 下载和解析 JSON

转载 作者:行者123 更新时间:2023-11-28 12:12:25 25 4
gpt4 key购买 nike

我陷入了一个概念上简单的问题。发生的事情是解析操作在下载操作的完成处理程序完成之前执行。因此,没有要解析的数据。您可以将以下代码直接放入文件中并运行它。

如何确保在解析操作运行之前完成下载?

import UIKit

let search = "https://api.nal.usda.gov/ndb/search/?format=json&q=butter&sort=n&max=25&offset=0&api_key=DEMO_KEY"

class ViewController: UIViewController {



override func viewDidLoad() {
super.viewDidLoad()

let fetch = FetchNBDNumbersOperation()
let parse = NDBParseOperation()

// 1
let adapter = BlockOperation() { [unowned parse, unowned fetch] in
parse.data = fetch.data
}

// 2
adapter.addDependency(fetch)
parse.addDependency(adapter)

// 3
let queue = OperationQueue()
queue.addOperations([fetch, parse, adapter], waitUntilFinished: true)
}
}

class FetchNBDNumbersOperation: Operation {

var data: Data?

override func main() {
let url = URL(string: search)!
let urlSession = URLSession.shared
let dataTask = urlSession.dataTask(with: url) { (jsonData, response, error) in
guard let jsonData = jsonData, let response = response else {
debugPrint(error!.localizedDescription)
return
}
self.data = jsonData
print("Response URL: \(String(describing: response.url?.absoluteString))")
}
dataTask.resume()
}
}

class NDBParseOperation: Operation {

var data: Data?
var nbdNumbers = [NBDNumber]()

override func main() {
let decoder = JSONDecoder()
do {
guard let jsonData = self.data else {
fatalError("No Data")
}
let dictionary = try decoder.decode( [String: USDAFoodSearch].self, from: jsonData )
for (_, foodlist) in dictionary {
for food in foodlist.item {
print("\(food.name) \(food.ndbno) \(food.group)")
let nbdNumber = NBDNumber(name: food.name, nbdNo: food.ndbno)
nbdNumbers.append(nbdNumber)
}
}
} catch {
print(error.localizedDescription)
}
}
}

struct NBDNumber {
var name: String
var nbdNo: String
}

struct USDAFoodSearch: Decodable {
let q: String
let sr: String
let ds: String
let start: Int
let end: Int
let total: Int
let group: String
let sort: String
let item: [USDAFood]

struct USDAFood: Decodable {
let offset: Int //Position in Array
let group: String
let name: String
let ndbno: String
let ds: String
}
}

最佳答案

在您的获取操作中,您恢复了 URLSessionDataTask。此时,该操作认为它已完成,因为它不知道其他线程上发生了什么,并且本质上不关心并发操作,并且它依赖于 (adapter) 启动。与此同时,URLSessionDataTask 仍在另一个线程上执行。

来自 Apple 关于 NSOperation 的文档

For non-concurrent operations, you typically override only one method:

  • main()

URLSessionDataTask 同时运行,因此您需要做更多的工作将它们包装在 NSOperation 中。为了包装并发操作,您需要:

...override the following methods and properties at a minimum:

start()

isAsynchronous

isExecuting

isFinished

NSOperation docs对此进行了相当多的详细介绍,但总结一下:您需要覆盖 start() 而不是 main() 并让您的实现保持操作状态日期。

关于json - 如何在 Swift 中使用 OperationQueue 下载和解析 JSON,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48014631/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com