Reputation: 143
My program pulls from an API to return appointment data into a widget. I set up a closure to handle pulling an unknown number of pages from the API. Each time loadResults is called, it queries the API, starting with page 1, and then checks to see if there are any pages left and calls itself again if any pages are remaining to pull. Once all pages of the API are pulled and loaded into my array, it stops running.
I'm loading the getAllResults function in my getTimeline function and would like to wait until it's finished running to then load my timeline Entry.
Is there a way to put an optional completion handler on getAllResults so I can use this function to then load my timeline entry once the completion handler finishes? Since I'm calling it multiple times I'd like to let it run recursively until finished and be able to alert the timeline it's finished and ready to load.
Current code:
func getAllResults(){
loadResults { (pageReturned) in
if pageReturned == Int(totalPages)! {
pages = 1
parseData(apptReturn: apptList)
//end the call
} else if pageReturned < Int(totalPages)! {
pages = pages + 1
getAllResults()
}
}
}
I was thinking something like this to name the completion handler and call it within the nested closure (but this doesn't work). Is there a way to reference the getAllResults completion within the loadResults closure?
func getAllResults(completedResults completion: @escaping (Bool) -> ()){
loadResults { (pageReturned) in
if pageReturned == Int(totalPages)! {
pages = 1
parseTodayData(apptReturn: apptList)
getAllResults(completedResults: true) //error: Cannot convert value of type 'Bool' to expected argument type '(Bool) -> ()'
//end the call
} else if pageReturned < Int(totalPages)! {
pages = pages + 1
getAllResults(completedResults: false). //error: Cannot convert value of type 'Bool' to expected argument type '(Bool) -> ()'
//
}
//
}
}
Upvotes: 2
Views: 1479
Reputation: 49590
Regardless of whether you need recursion or not, for an async call you'd need a completion handler, so that the caller can know when the operation has completed.
If you want to use recursion, you can pass the completion handler down to the next recursive invocation, and call it when completed.
func getResults(onCompleted handler: @escaping () -> Void) {
loadResults { pageReturned in
let needToLoadMore = ... // determine if you need to load more pages
// other side effects
if needToLoadMore {
getResults(onCompleted: handler)
} else {
handler()
}
}
}
Upvotes: 5