I am using a UITableView to present a variety of viewControllers. Depending on which index is clicked, it will present a different view controller, which can then be dismis
As already mentioned, one fix is to run any presenting of the view controllers on the main thread explicitly or to use performSelector.
However, it wasn't clear to me why this was a fix because I was under the impression that didSelectRow runs on the main thread anyway. It wasn't until I read this answer that things became clear for me.
For details, read the linked answer, but in short it seems that this affects cells that have a selection style of none. This turns off the (by default grey) animation that occurs when a cell is selected which means that the run loop is not triggered for when didSelectRow is called. So when you go to present another view controller the animation that actually presents it doesn't immediately occur on the run loop.
The solution of simply running it on the main thread is not a direct fix. You actually just need to trigger the run loop, such as by supplying it with some code and it will work. For example:
dispatch_async(dispatch_get_main_queue(), {})
[self presentViewController:viewController animated:YES completion:nil]
will also fix it. This has the side effect of triggering the run loop when the view controller is presented so the animation of the view controller now happens instantly. This is also why calling performSelector works.