前提・実現したいこと
SwiftUIを利用してアプリを開発しています。
DispatchGroup
を利用するwhile
文から取得する値を、同じwhile
文をloopさせるかどうかの条件の値として利用したいです。
例えば、下記のコードに載せているメソッドを以下のように呼んだ場合:
makeGetCallDateOverSetTemp(start_date:"2020-11-01", set_temp:100)
- 1回目 loop -> totalTemp = 20 (2020-11-01の気温は20℃)
- 2回目 loop -> totalTemp = 50 (2020-11-02の気温は30℃)
- 3回目 loop -> totalTemp = 80 (2020-11-03の気温は30℃)
- 4回目 loop -> totalTemp = 105 (2020-11-04の気温は25℃)
5番目は、while文の条件としているtotalTempが、2番目の引数に渡した100を超えるため、loopが止まる
という動きにしたいです。
該当のソースコード
AppState.swift
swift
1@Published var weatherInfos:[WeatherInfos]? 2 3 4func makeGetCallDateOverSetTemp(start_date:String, set_temp:Int){ 5 6 let start_date = self.dateFromString(string: start_date, format: "yyyy/MM/dd") 7 var addDays = 0 8 var totalTemp:Float = 0.0 9 10 let group = DispatchGroup() 11 12 // Set up the URL request 13 while Float(set_temp) < totalTemp { 14 15 let start_date = Calendar.current.date(byAdding: .day, value: addDays, to: start_date) 16 let url_start_date = self.stringFromDate(date: start_date!, format: "yyyy-MM-dd") 17 18 let endpoint: String = "https://sample.com/api/weather/?start_date=(url_start_date)" 19 addDays += 1 20 21 guard let url = URL(string: endpoint) else { 22 print("Error: cannot create URL") 23 continue 24 } 25 var urlRequest = URLRequest(url: url) 26 urlRequest.addValue("token xxxxxxxxxxx", forHTTPHeaderField: "authorization") 27 // set up the session 28 let config = URLSessionConfiguration.default 29 let session = URLSession(configuration: config) 30 // make the request 31 group.enter() 32 let task = session.dataTask(with: urlRequest) {(data, response, error) in 33 guard error == nil else { 34 print("error calling GET") 35 return 36 } 37 // make sure we got data 38 guard let responseData = data else { 39 print("Error: did not receive data") 40 return 41 } 42 // check for any errors 43 defer { group.leave()} 44 // parse the result as JSON, since that's what the API provides 45 DispatchQueue.main.async { 46 do{ 47 self.weatherInfos = try JSONDecoder().decode([WeatherInfos].self, from: responseData) 48 for info in self.weatherInfos!{ 49 totalTemp += info.temp 50 } 51 }catch{ 52 print("Error: did not decode") 53 return 54 } 55 } 56 } 57 task.resume() 58 } 59 group.notify(queue: .main){ 60 print(url_start_date) 61 } 62} 63 64func stringFromDate(date: Date, format: String) -> String { 65 let formatter: DateFormatter = DateFormatter() 66 formatter.calendar = Calendar(identifier: .gregorian) 67 formatter.dateFormat = format 68 return formatter.string(from: date) 69} 70 71func dateFromString(string: String, format: String) -> Date { 72 let formatter: DateFormatter = DateFormatter() 73 formatter.calendar = Calendar(identifier: .gregorian) 74 formatter.dateFormat = format 75 return formatter.date(from: string) ?? Date() 76}
jsonModel.swift
swift
1struct WeatherInfos:Codable,Identifiable { 2 var id: Int 3 var temp: Float 4}
追記
swift
1 func getTemperature(date: String) -> Double? { 2 let semaphore = DispatchSemaphore(value: 0) 3 4 let endpoint: String = "https://sample.com/api/weather_ave_day/?date=(date)" 5 6 let url = URL(string: endpoint) 7 8 var urlRequest = URLRequest(url: url!) 9 urlRequest.addValue("token xxxxxxxxxxxxxxxxx", forHTTPHeaderField: "authorization") 10 // set up the session 11 let config = URLSessionConfiguration.default 12 let session = URLSession(configuration: config) 13 14 var temperature: Double = 0.0 15 16 let task = session.dataTask(with: urlRequest) {(data, response, error) in 17 guard error == nil else { 18 print("error calling GET") 19 return 20 } 21 // make sure we got data 22 guard let responseData = data else { 23 print("Error: did not receive data") 24 return 25 } 26 DispatchQueue.main.async { 27 do{ 28 self.weatherInfos = try JSONDecoder().decode([WeatherInfos].self, from: responseData) 29 for info in self.weatherAveInfos!{ 30 temperature += Double(info.ave_temp) 31 } 32 33 print("weatherInfos:(self.weatherInfos as Any)") // 11.9 34 }catch{ 35 print("Error: did not decode") 36 return 37 } 38 } 39 semaphore.signal() 40 } 41 task.resume() 42 semaphore.wait() 43 44 print("returnValue:(temperature as Any)") // 0.0 45 return temperature 46 }
メソッドの呼び出し
Button(action: { appState.getTemperature(date: "2020-11-11") } ) { Text("取得") }
実行結果
console
1returnValue:0.0 2weatherInfos:Optional([Sample.WeatherInfos(id: 6, temp: 11.9)])
補足情報(FW/ツールのバージョンなど)
Xcode:Version 12.0.1
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/11/19 08:09 編集
2020/11/19 08:16
2020/11/19 08:23
2020/11/19 08:36
2020/11/19 08:48
2020/11/19 08:57
2020/11/19 10:05
2020/11/20 01:35
2020/11/20 01:46
2020/11/20 06:02