Reputation: 4107
In my app I have a view controller, that I present modally. In this view controller I have a table view. Whenever user makes a selection in a table view, I dismiss the view controller.
The problem is that sometimes the view controller is not getting dismissed or getting dismissed after a long delay (5-7 seconds) even though the dismiss function is called.
Here is my code:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
if tableView == self.quarterTableView
{
self.delegate?.modalViewController(modalVC: self, dismissedWithValue:self.quarterPeriods[indexPath.row])
}
else if tableView == self.monthTableView
{
self.delegate?.modalViewController(modalVC: self, dismissedWithValue: self.monthPeriods[indexPath.row])
}
Print("didSelectRowAt dismiss")
self.dismiss(animated: true) {
Print("finished")
}
}
Any help is highly appreciated.
EDIT:
I resolved the issue by using:
DispatchQueue.main.async
{
self.dismiss(animated: true) {
DDLogDebug("finished")
}
}
Is there any harm done by doing so?
Upvotes: 4
Views: 2963
Reputation: 345
This is a bit of an old thread but it might help others.
I have run into the same problem recently (with XCode 10.1, Swift 4.2) and found that, yes, the above solution of wrapping the dismiss in a DispatchQueue.main.async works. However, it makes no sense since the thread executing the dismiss cannot be anything but the main thread.
My situation is slightly different in that I call back to a delegate (the delegate being the VC that presented the modal view in the first place) but the behaviour is identical to the OP's description - if I dismiss the modal with a Cancel button, response through to the dismiss completion block is instantaneous whereas if I dismiss via selecting a row in the tableView then there is a 7-10 second delay before the dismiss completion block is executed. Testing what thread is running before issuing dismiss and inside the completion callback both show that it is the main thread (actually, it can't be anything else....). So, while wrapping the dismiss in a DispatchQueue.main.async clearly works, it doesn't make any sense.
See the code snippet below, addition of the line that deselects the row in the table view also fixes the delay problem. Weird.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
Logger.debug("In tableView delegate: didSelectRowAt")
selectedItem = discoveredPeripherals[indexPath.row][kPeripheralUuidKey] ?? nil
// Grabbing the data I need based on the selected row and then deselecting the row
// fixes the delay problem
tableView.deselectRow(at: indexPath, animated: false) // <<---- fixes the delay
discoveredPeripherals = []
if let dd = dismissalDelegate { dd.didCompletePresenting(viewController: self) }
else { self.dismiss(animated: true, completion: {
Logger.debug("Warning: Invalid (nil) dismissal delegate, dismissing self")
})
}
}
Hope that helps someone... I notice from other posts on SO that an orthogonal issue exists when presenting a VC based on a tableView row selection....
Upvotes: 3
Reputation: 164
No harm. You just let main thread do two tasks at the same time.
Upvotes: 2
Reputation: 5554
if you want something on the UI to happen right away, execute it on the main queue
DispatchQueue.main.async(execute: {
self.dismiss(animated: true) {
Print("finished")
})
Upvotes: 6
Reputation: 362
try to use a dispatch DispatchQueue
DispatchQueue.main.async(execute: {
})
Upvotes: 5