前提・実現したいこと
SwiftUIを利用してアプリを開発しています。
Combine
frameworkを使う非同期処理を、他のメソッド内while
のloop処理の中で、複数回行い、それぞれの処理結果を利用したいです。
sink()
を利用し、値の取得が終了する際の処理の中で、次のメソッド(while
のloop処理を行う)に値を渡しているのですが、うまく動作しません。
動作概要
0. 指定の日付の平均気温を取得するエンドポイントを利用し、気温を取得する(記載のコードの場合は15.0)メソッドを準備する
- 1のメソッドをwhile文で複数回行い(記載のコードの場合は3回)、合計の気温の値を利用する(記載のコードの場合は45.0)
どのような対応をすれば、期待する動作になるでしょうか?
発生している問題
期待する表示
counter:1 totalTemp:15.0 counter:2 totalTemp:30.0 counter:3 totalTemp:45.0 2020-11-22 23:15:03.755907+0700 Sample[84786:7191186] [] nw_protocol_get_quic_image_block_invoke dlopen libquic failed ---------- dayTemp:15.0 receiveCompletion:finished
実際の表示
counter:1 totalTemp:0.0 counter:2 totalTemp:0.0 counter:3 totalTemp:0.0 2020-11-22 23:15:03.755907+0700 Sample[84786:7191186] [] nw_protocol_get_quic_image_block_invoke dlopen libquic failed ---------- dayTemp:15.0 receiveCompletion:finished
該当のソースコード
swift
1 var weatherInfos:WeatherInfos? 2 3 func whileTempCombine(date: String,getTemp:@escaping(Float)->Void){ 4 5 var counter:Int = 0 6 var totalTemp:Float = 0.0 7 8 while counter < 3 9 { 10 counter += 1 11 self.getTemperatureCombine(block_no: block_no, date: date, getDayTemp: {returnData in 12 totalTemp += returnData}) 13 print("counter:(counter)") 14 print("totalTemp:(totalTemp)") 15 } 16 getTemp(totalTemp) 17 } 18 19 20 var cancellable: AnyCancellable? = nil 21 22 func getTemperatureCombine(date: String,getDayTemp:@escaping(Float)->Void){ 23 var dayTemp:Float = 0.0 24 25 let endpoint: String = "https://sample.com/api/temp_day/?date=(date)" 26 let url = URL(string: endpoint) 27 let urlRequest = URLRequest(url: url!) 28 29 cancellable = URLSession.shared.dataTaskPublisher(for: urlRequest) 30 .map({(data, res) in 31 return data 32 }) 33 .decode(type: [WeatherInfos].self, decoder: JSONDecoder()) 34 .sink(receiveCompletion: {completion in 35 print("receiveCompletion:(completion)") 36 print("dayTemp:(dayTemp)") // 15.0 37 getDayTemp(dayTemp) 38 } 39 , receiveValue: {value in 40 for info in value{ 41 dayTemp += info.temp 42 print("dayTemp:(dayTemp)") 43 } 44 }) 45 } 46 47 struct WeatherInfos:Codable,Identifiable { 48 var id: Int 49 var temp: Float 50 } 51
ContentView.swift
swift
1import SwiftUI 2 3struct ContentView: View { 4 5 @EnvironmentObject var appState: AppState 6 @State var temp:Float = 0.0 7 8 var body: some View { 9 VStack{ 10 if appState.isLoading{ 11 Progress() 12 } 13 Text(String(temp)) 14 Button(action:{ 15 appState.whileTempCombine(date: "2020-11-01", getTemp: { returnData in 16 temp = returnData 17 }) 18 19 }){ 20 Text("実行") 21 } 22 } 23 } 24}
試したこと
getDayTemp(dayTemp)
の処理をreceiveValue
クロージャーの中で行っても、同じ結果となります。
補足情報(FW/ツールのバージョンなど)
Xcode:Version 12.0.1
iOS:13.0
あなたの回答
tips
プレビュー