概念的に単純な問題に悩まされました。何が起こっているのは、ダウンロード操作の完了ハンドラが終了する前に解析操作が実行されていることです。その結果、解析するデータはありません。次のコードをファイルにドロップして実行することができます。SwiftでOperationQueueを使用してJSONをダウンロードして解析する方法
パーズ操作を実行する前にダウンロードが完了していることを確認するにはどうすればよいですか?
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
}
}
私の謙虚な意見では、私はあなただけ** 1 **と「構文解析を」フェッチ 'を含む操作を含めるには、この再設計をすべきだと思います。したがって、データを取得してデータを解析し終えたら、両方とも互いに関連しているため、両方の操作を別々に行う必要はありません。 –