如何使用 DispatchGroup 在 while 循环中将值设置为条件?
How to set a value as a condition in while loop using DispatchGroup?
我目前正在使用 SwiftUI 开发应用程序。
我想使用从使用 DispatchGroup
的 while
循环创建的值作为 while
循环的条件。
但是我的代码不起作用...
我的目标是从开始日期开始获得超过设定总温度的日期。
我该如何解决这个问题?
已更新
例如:
如果我像下面这样调用方法。
makeGetCallDateOverSetTemp(start_date:"2020-11-01", set_temp:100)
- 第一个循环-> totalTemp = 20(2020-11-01的温度是20℃)
- 第2次循环-> totalTemp = 50(2020-11-02温度为30℃)
- 第3次循环-> totalTemp = 80(2020-11-03的温度为30℃)
- 第4次循环-> totalTemp = 105(2020-11-04温度为25℃)
while
循环在此处停止并获得 2020-11-04
作为超过设定温度的那一天。
AppState.swift
@Published var weatherInfos:[WeatherInfos]?
func makeGetCallDateOverSetTemp(start_date:String, set_temp:Int){
let start_date = self.dateFromString(string: start_date, format: "yyyy/MM/dd")
var addDays = 0
var totalTemp:Float = 0.0
let group = DispatchGroup()
// Set up the URL request
while Float(set_temp) < totalTemp {
let start_date = Calendar.current.date(byAdding: .day, value: addDays, to: start_date)
let url_start_date = self.stringFromDate(date: start_date!, format: "yyyy-MM-dd")
let endpoint: String = "https://sample.com/api/weather/?start_date=\(url_start_date)"
addDays += 1
guard let url = URL(string: endpoint) else {
print("Error: cannot create URL")
continue
}
var urlRequest = URLRequest(url: url)
urlRequest.addValue("token xxxxxxxxxxx", forHTTPHeaderField: "authorization")
// set up the session
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)
// make the request
group.enter()
let task = session.dataTask(with: urlRequest) {(data, response, error) in
guard error == nil else {
print("error calling GET")
return
}
// make sure we got data
guard let responseData = data else {
print("Error: did not receive data")
return
}
// check for any errors
defer { group.leave()}
// parse the result as JSON, since that's what the API provides
DispatchQueue.main.async {
do{
self.weatherInfos = try JSONDecoder().decode([WeatherInfos].self, from: responseData)
for info in self.weatherInfos!{
totalTemp += info.temp
}
}catch{
print("Error: did not decode")
return
}
}
}
task.resume()
}
group.notify(queue: .main){
print(url_start_date)
}
}
func stringFromDate(date: Date, format: String) -> String {
let formatter: DateFormatter = DateFormatter()
formatter.calendar = Calendar(identifier: .gregorian)
formatter.dateFormat = format
return formatter.string(from: date)
}
func dateFromString(string: String, format: String) -> Date {
let formatter: DateFormatter = DateFormatter()
formatter.calendar = Calendar(identifier: .gregorian)
formatter.dateFormat = format
return formatter.date(from: string) ?? Date()
}
jsonModel.swift
struct WeatherInfos:Codable,Identifiable {
var id: Int
var temp: Float
}
条件依赖于异步任务结果的while
循环是不可能的。
这是一个独立的通用示例,在 Playground 中递归到 运行。
静态数据是结构体、数组、队列和阈值
struct Item {
let date : String
let values : [Int]
}
let items = [Item(date: "2020-02-01", values: [1, 3, 5]),
Item(date:"2020-02-02", values:[2, 4, 6]),
Item(date: "2020-02-03", values:[3, 5, 7])]
let queue = DispatchQueue(label: "Foo")
let threshold = 25
变量是指数和积温
var temp = 0
var index = 0
如果尚未达到阈值,函数 getData
会调用自身传递下一个 item
。异步任务用asyncAfter
.
模拟
最终函数 notify
被调用。
func notify(date : String) {
DispatchQueue.main.async{ print(date, temp) }
}
func getData(date: String, values :[Int]) {
queue.asyncAfter(deadline: .now() + 1) {
for value in values {
temp += value
if temp >= threshold {
notify(date: date)
return
}
}
index += 1
if index < items.count {
let nextItem = items[index]
getData(date: nextItem.date, values: nextItem.values)
} else {
notify(date: "\(date) – temperature below threshold")
}
}
}
let firstItem = items[index]
getData(date: firstItem.date, values: firstItem.values)
我目前正在使用 SwiftUI 开发应用程序。
我想使用从使用 DispatchGroup
的 while
循环创建的值作为 while
循环的条件。
但是我的代码不起作用... 我的目标是从开始日期开始获得超过设定总温度的日期。
我该如何解决这个问题?
已更新
例如:
如果我像下面这样调用方法。
makeGetCallDateOverSetTemp(start_date:"2020-11-01", set_temp:100)
- 第一个循环-> totalTemp = 20(2020-11-01的温度是20℃)
- 第2次循环-> totalTemp = 50(2020-11-02温度为30℃)
- 第3次循环-> totalTemp = 80(2020-11-03的温度为30℃)
- 第4次循环-> totalTemp = 105(2020-11-04温度为25℃)
while
循环在此处停止并获得 2020-11-04
作为超过设定温度的那一天。
AppState.swift
@Published var weatherInfos:[WeatherInfos]?
func makeGetCallDateOverSetTemp(start_date:String, set_temp:Int){
let start_date = self.dateFromString(string: start_date, format: "yyyy/MM/dd")
var addDays = 0
var totalTemp:Float = 0.0
let group = DispatchGroup()
// Set up the URL request
while Float(set_temp) < totalTemp {
let start_date = Calendar.current.date(byAdding: .day, value: addDays, to: start_date)
let url_start_date = self.stringFromDate(date: start_date!, format: "yyyy-MM-dd")
let endpoint: String = "https://sample.com/api/weather/?start_date=\(url_start_date)"
addDays += 1
guard let url = URL(string: endpoint) else {
print("Error: cannot create URL")
continue
}
var urlRequest = URLRequest(url: url)
urlRequest.addValue("token xxxxxxxxxxx", forHTTPHeaderField: "authorization")
// set up the session
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)
// make the request
group.enter()
let task = session.dataTask(with: urlRequest) {(data, response, error) in
guard error == nil else {
print("error calling GET")
return
}
// make sure we got data
guard let responseData = data else {
print("Error: did not receive data")
return
}
// check for any errors
defer { group.leave()}
// parse the result as JSON, since that's what the API provides
DispatchQueue.main.async {
do{
self.weatherInfos = try JSONDecoder().decode([WeatherInfos].self, from: responseData)
for info in self.weatherInfos!{
totalTemp += info.temp
}
}catch{
print("Error: did not decode")
return
}
}
}
task.resume()
}
group.notify(queue: .main){
print(url_start_date)
}
}
func stringFromDate(date: Date, format: String) -> String {
let formatter: DateFormatter = DateFormatter()
formatter.calendar = Calendar(identifier: .gregorian)
formatter.dateFormat = format
return formatter.string(from: date)
}
func dateFromString(string: String, format: String) -> Date {
let formatter: DateFormatter = DateFormatter()
formatter.calendar = Calendar(identifier: .gregorian)
formatter.dateFormat = format
return formatter.date(from: string) ?? Date()
}
jsonModel.swift
struct WeatherInfos:Codable,Identifiable {
var id: Int
var temp: Float
}
条件依赖于异步任务结果的while
循环是不可能的。
这是一个独立的通用示例,在 Playground 中递归到 运行。
静态数据是结构体、数组、队列和阈值
struct Item {
let date : String
let values : [Int]
}
let items = [Item(date: "2020-02-01", values: [1, 3, 5]),
Item(date:"2020-02-02", values:[2, 4, 6]),
Item(date: "2020-02-03", values:[3, 5, 7])]
let queue = DispatchQueue(label: "Foo")
let threshold = 25
变量是指数和积温
var temp = 0
var index = 0
如果尚未达到阈值,函数 getData
会调用自身传递下一个 item
。异步任务用asyncAfter
.
最终函数 notify
被调用。
func notify(date : String) {
DispatchQueue.main.async{ print(date, temp) }
}
func getData(date: String, values :[Int]) {
queue.asyncAfter(deadline: .now() + 1) {
for value in values {
temp += value
if temp >= threshold {
notify(date: date)
return
}
}
index += 1
if index < items.count {
let nextItem = items[index]
getData(date: nextItem.date, values: nextItem.values)
} else {
notify(date: "\(date) – temperature below threshold")
}
}
}
let firstItem = items[index]
getData(date: firstItem.date, values: firstItem.values)