我有一个我不明白为什么的错误
我的问题是我有三个函数,其名称是sendCourse,sendRequire,sendStep
第一个函数sendCourse很简单。此功能只是一个基本的网络查询
sendRequire和sendStep函数类似。它们包含一个for循环,它迭代一个数组以将数组的每个元素发送到服务器。在此函数中,必须等到上一个网络请求完成(该元素被发送到服务器)才能发送数组的下一个元素。
最后,我有另一个名为sendRecipe的方法。此方法执行sendCourse,sendRequire,sendStep。 senRecipe必须等待sendCourse完成。当sendCourse完成后,sendRecipe函数必须执行sendRequire。然后sendRecipe必须等到sendRequire完成才能执行sendStep
最后,我有一个调用sendRecipe的按钮
当我点击按钮时,我的应用程序崩溃了
这是我的代码:
private func sendCourse(success: @escaping(() -> Void), errorHandling: @escaping((String) -> Void)) {
let dataCourse:[String:String] = [
"name":self.course.name,
"course_type_id":String(self.course.type.id),
"country_code":self.course.country.countryCode,
"dishes_number":String(self.course.dishesNumber),
"description":self.course.description
]
APIManager.sharedInstance.put(action: .courses, data: dataCourse, onSuccess: {(responseCode, data) -> Void in
if responseCode == 201 {
let jsonDecoder = JSONDecoder()
if let course = try? jsonDecoder.decode(Courses.self, from: data) {
self.course = course
success()
} else {
errorHandling("service unavailable")
}
} else {
errorHandling("service unavailable")
}
}, onFailure: {(error) -> Void in
errorHandling(error.localizedDescription)
})
}
private func sendRequire(success: @escaping(() -> Void), errorHandling: @escaping((String) -> Void)) {
let requireGroup = DispatchGroup()
var fail = false
for require in requires {
if fail == true {
break
}
requireGroup.enter()
let dataRequire:[String:String] = [
"course_id":String(self.course.id!),
"ingredient_id":String(require.ingredient.id),
"quantity":String(format: "%f", require.quantity)
]
APIManager.sharedInstance.put(action: .requires, data: dataRequire, onSuccess: {(responseCode, data) -> Void in
if responseCode == 201 {
requireGroup.leave()
success()
} else {
requireGroup.leave()
fail = true
errorHandling("Service unavailable")
}
}, onFailure: {(error) -> Void in
requireGroup.leave()
fail = true
errorHandling(error.localizedDescription)})
}
requireGroup.wait()
}
private func sendStep(success: @escaping(() -> Void), errorHandling: @escaping((String) -> Void)) {
let stepGroup = DispatchGroup()
var fail = false
for (index, step) in self.steps.enumerated() {
if fail == true {
break
}
stepGroup.enter()
var previousStepId=0
if index == 0 {
previousStepId = 0
} else {
previousStepId = steps[index-1].id!
}
let dataStep:[String:String] = [
"course_id":String(self.course.id!),
"description":step.description,
"duration_hours":String(step.durationHours),
"duration_minutes":String(step.durationMinutes),
"duration_seconds":String(step.durationSeconds),
"previous_step_id":String(previousStepId)
]
APIManager.sharedInstance.put(action: .steps, data: dataStep, onSuccess: {(responseCode, data) -> Void in
if responseCode == 201 {
let jsonDecoder = JSONDecoder()
if let step = try? jsonDecoder.decode(Step.self, from: data) {
self.steps[index] = step
stepGroup.leave()
success()
} else {
fail = true
errorHandling("service unavailable")
stepGroup.leave()
}
} else {
fail = true
errorHandling("service unavailable")
stepGroup.leave()
}
}, onFailure: {(error) -> Void in
errorHandling(error.localizedDescription)
fail = true
stepGroup.leave()
})
stepGroup.wait()
}
}
func sendRecipe(errorHandling: @escaping((String) -> Void)) {
DispatchQueue.global(qos: .background).sync {
self.sendCourse(success: {}, errorHandling: errorHandling)
}
DispatchQueue.global(qos: .background).sync {
self.sendRequire(success: {}, errorHandling: errorHandling)
}
DispatchQueue.global(qos: .background).sync {
self.sendStep(success: {}, errorHandling: errorHandling)
}
}
here is the code of the button:
@IBAction func doneBarButtonItemTapped(_ sender: UIBarButtonItem) {
recipe?.steps = steps
recipe?.sendRecipe(errorHandling: {(error) -> Void in
DispatchQueue.main.async {
let alert = UIAlertController(title: "Error", message: error, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "dismiss", style: .default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
})
}
这是应用程序崩溃时我的屏幕捕获: capture of Xcode when the app crash 先谢谢你了
答案 0 :(得分:0)
我找到了解决方案: 这是应该工作的代码:
private func sendCourse(success: @escaping(() -> Void), errorHandling: @escaping((String) -> Void)) {
let dataCourse:[String:String] = [
"name":self.course.name,
"course_type_id":String(self.course.type.id),
"country_code":self.course.country.countryCode,
"dishes_number":String(self.course.dishesNumber),
"description":self.course.description
]
DispatchQueue.global(qos: .utility).sync {
APIManager.sharedInstance.put(action: .courses, data: dataCourse, onSuccess: {(responseCode, data) -> Void in
print(responseCode, String(data:data, encoding: String.Encoding.utf8)!)
if responseCode == 201 {
let jsonDecoder = JSONDecoder()
if let course = try? jsonDecoder.decode(Courses.self, from: data) {
self.course = course
success()
} else {
errorHandling("service unavailable")
}
} else {
errorHandling("service unavailable")
}
}, onFailure: {(error) -> Void in
errorHandling(error.localizedDescription)
})
}
}
private func sendRequire(success: @escaping(() -> Void), errorHandling: @escaping((String) -> Void)) {
let requireGroup = DispatchGroup()
var fail = false
for (index, require) in requires.enumerated() {
if fail == true {
break
}
requireGroup.enter()
let dataRequire:[String:String] = [
"course_id":String(self.course.id ?? 0),
"ingredient_id":String(require.ingredient.id),
"quantity":String(format: "%f", require.quantity)
]
APIManager.sharedInstance.put(action: .requires, data: dataRequire, onSuccess: {(responseCode, data) -> Void in
print(responseCode, String(data:data, encoding: String.Encoding.utf8)!)
if responseCode == 201 {
requireGroup.leave()
} else {
fail = true
errorHandling("Service unavailable")
}
}, onFailure: {(error) -> Void in
fail = true
errorHandling(error.localizedDescription)
})
requireGroup.wait()
if index==requires.count-1 {
success()
}
}
}
private func sendStep(success: @escaping(() -> Void), errorHandling: @escaping((String) -> Void)) {
let stepGroup = DispatchGroup()
var fail = false
for (index, step) in self.steps.enumerated() {
if fail == true {
break
}
stepGroup.enter()
var previousStepId=0
if index == 0 {
previousStepId = 0
} else {
previousStepId = steps[index-1].id!
}
let dataStep:[String:String] = [
"course_id":String(self.course.id ?? 0),
"description":step.description,
"duration_hours":String(step.durationHours),
"duration_minutes":String(step.durationMinutes),
"duration_seconds":String(step.durationSeconds),
"previous_step_id":String(previousStepId)
]
APIManager.sharedInstance.put(action: .steps, data: dataStep, onSuccess: {(responseCode, data) -> Void in
print(responseCode, String(data:data, encoding: String.Encoding.utf8)!)
if responseCode == 201 {
let jsonDecoder = JSONDecoder()
if let step = try? jsonDecoder.decode(Step.self, from: data) {
self .steps[index] = step
stepGroup.leave()
} else {
fail = true
errorHandling("service unavailable")
}
} else {
fail = true
errorHandling("service unavailable")
}
}, onFailure: {(error) -> Void in
errorHandling(error.localizedDescription)
fail = true
})
stepGroup.wait()
if index==steps.count-1 {
success()
}
}
}
func sendRecipe(errorHandling: @escaping((String) -> Void)) {
let recipeGroup = DispatchGroup()
recipeGroup.enter()
self.sendCourse(success: {recipeGroup.leave()}, errorHandling: errorHandling)
recipeGroup.wait()
recipeGroup.enter()
self.sendRequire(success: {recipeGroup.leave()}, errorHandling: errorHandling)
recipeGroup.wait()
recipeGroup.enter()
self.sendStep(success: {recipeGroup.leave()}, errorHandling: errorHandling)
}