OpenWetherMapのAPIをParsesしました。取得したデータを使って判定を行いたかったのですが、クロージャの中が非同期になっているようで、後続の処理が抜けてしまいます。
Swiftで複数の非同期処理の完了時に処理を行うこの記事を見るに、
DispatchGroupメソッドを使うと終了判定が取れるようだったので、使ってみたのですが、処理完了前に条件式を判定してしまいます。
Swift
1 override func viewDidLoad() { 2 super.viewDidLoad() 3 var jData:Root? 4 let url = URL(string: "https://api.openweathermap.org/data/2.5/weather?q=Hachioji&appid=568cc88fc88a619182325a1338854669")! 5 let request = URLRequest(url: url) 6 let dispatchGroup = DispatchGroup() 7 8 task = URLSession.shared.dataTask(with: request) { (data, response, error) in 9 guard let data = data else{return} 10 do{ 11 dispatchGroup.enter() 12 jData = try JSONDecoder().decode(Root.self, from: data) 13 } catch let e { 14 print(e) 15 } 16 } 17 task.resume() 18 19 dispatchGroup.notify(queue: .main){ 20 print("<<<<<<<<<<<<<<<<<<<") 21 if let data = jData{ 22 print(data.weather[0].main) 23 } 24 print(">>>>>>>>>>>>>>>>>>>>>>>>>") 25 } 26 27 }
データが入る前に判定をされてしまっているので天気のデータがprintされずに上下のprint文の文字だけが出力されています
DEBUG
1<<<<<<<<<<<<<<<<<<< 2>>>>>>>>>>>>>>>>>>>>>>>>>
処理の完了はどのように検知すれば良いのでしょうか
※追記
クロージャの中でやればいいんじゃないかという意見をいただいたので追記します。
データを取得する部分だけ別クラスにしようと考えています。
雨かを判定して雨の時だけアプリの挙動を変えようと思っています。クロージャの中でreturnをしても元の関数を抜けることができないので非同期処理の終了を検知したいと考えました。
Swift
1class WetherClient: UIView { 2 private let openWetherMapAPI = "https://api.openweathermap.org/data/2.5/weather?q=Hachioji&appid=568cc88fc88a619182325a1338854669" 3 private var wether:Root! 4 5 func judgeWether() -> Bool{ 6 let url = URL(string: openWetherMapAPI)! 7 let request = URLRequest(url: url) 8 var task = URLSession.shared.dataTask(with: request){(data, response, error) in 9 guard let data = data else{return} 10 do{ 11 let jsonData = try JSONDecoder().decode(Root.self, from: data) 12 print(jsonData.weather[0].main) 13 self.wether = jsonData 14 } catch let e{ 15 print(e) 16 } 17 } 18 task.resume() 19 if let data = wether{ 20 if(data.weather[0].main == "Rain"){ 21 print(data.weather[0].main) 22 return true 23 } 24 } 25 print("jsonData:(wether.weather[0].main)") 26 return false 27 } 28} 29
※追記10/30
クロージャについて完璧には理解できていないと思いますがSwiftのクロージャについて整理してみた。という記事を参考にして、真似して実装を行なってみました。
ですが、wetherの値を確認するためにprintの部分にブレイクポイントを貼って値が入っているかを確認したのですが,しゅとくできておらずnullになってしまっていました
Swift
1class RainChecker: Any{ 2 private let openWetherMapAPI = "https://api.openweathermap.org/data/2.5/weather?q=Hachioji&appid=568cc88fc88a619182325a1338854669" 3 4 func judgeWether() -> Bool{ 5 6 var wether:Root? 7 getJsonData{(jsonData) in wether = jsonData} 8// if let data = wether{ 9// if(data.weather[0].main == "Rain"){ 10// print(data.weather[0].main) 11// return true 12// } 13// } 14// print("jsonData:(wether?.weather[0].main)") 15// return false 16 print(wether) 17 return true 18 } 19 func getJsonData(wetherData:@escaping (_ response: Root)->Void){ 20 let url = URL(string: openWetherMapAPI)! 21 let request = URLRequest(url: url) 22 23 24 var task = URLSession.shared.dataTask(with: request){(data, response, error) in 25 guard let data = data else{return} 26 do{ 27 let jsonData = try JSONDecoder().decode(Root.self, from: data) 28 wetherData(jsonData) 29 } catch let e{ 30 print(e) 31 } 32 33 } 34 task.resume() 35 } 36} 37
回答1件
あなたの回答
tips
プレビュー