My UITableView needs 2 clicks to show the detail page of the selected cell : one for selection and another one for show the detail view. I would like one clic to directly show the detail view of the clicked cell.
I use a modal segue with this method inside my UITableViewManager.m :
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:@"showDetail"]) {
NSIndexPath *indexPath = [playerList indexPathForSelectedRow];
TCPlayerStat *object = _objects[indexPath.row];
[[segue destinationViewController] setPlayerStat:object];
}
}
I can't work with a push segue because I don't have Navigation Controller (and don't really want to).
I've looked in the TableView Attribute Inspector but didnt find out anything relevant for this. I have Selection "Single Selection" selected and "Show Selection on Touch" checked. I don't know if this is possible and if it is, where to look..
Thanks for your help.
EDIT 1: When I write the two methods like this, it still doesn't work (needs 2 clicks) and I have a new warning log:
"Warning: Attempt to present TCDetailViewController: 0xa27b900 on TCRootViewController: 0xa24f050 while a presentation is in progress!"
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier:@"showDetail" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:@"showDetail"]) {
NSIndexPath *indexPath = [playerList indexPathForSelectedRow];
TCPlayerStat *object = _objects[indexPath.row];
TCDetailViewController *detailViewController = [segue destinationViewController];
[detailViewController setPlayerStat:object];
}
}
EDIT 2: I don't know why, but sometimes it works perfectly and doesn't need a second click on the table view. Can't find out :/
Solution below
A solution that works for me (XCode 9.2) and seems easy, but still allows for None
for the Selection is :
As @Tulleb says, in the storyboard use anything but None
for the Table View Cell
"Selection", but then set it to .none
in the code.
For example, like this...
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tv.dequeueReusableCell(withIdentifier: "cell")
cell?.selectionStyle = .none // This is the important line
I already had the selection attribute set to "Default" and was still experiencing the two-click problem. That suggestion did, however, point to a related solution. In didSelectRowAtIndexPath, call:
self.tableView.deselectRowAtIndexPath(indexPath, animated: false)
(I'm using Swift, obviously.)
I fond out what the problem was!
I changed a parameter on the Storyboard that I shouldn't have. I wanted the selection cell not to display a background highlight color when I click on it, but it seems the Segue is based on it to work decently.
HOW TO FIX: In the storyboard, select your Table View Cell in the Navigator and don't chose the "None" option in "Selection" (Attributes Inspector). "Blue", "Gray" or "Default" seems to work nice.
I think the more correct way to solve this problem is to perform any action on Main thread, in your case triggering the segue:
Objective-C
dispatch_async(dispatch_get_main_queue(), ^{
[self performSegueWithIdentifier:@"showDetail" sender:self];
});
Swift
DispatchQueue.main.async {
self.performSegue(withIdentifier: "showDetail", sender: self)
}
It's actually a bug, related to the main RunLoop and tableViewCell, while selectionStyles force RunLoop to be awake (as it has to process the animation), if you don't have selectionStyle, plus you don't do any startup animations inside your presented viewController, RunLoop will go asleep sometimes.
If you, for some reason, don't want to do the action (in your case it's triggering the segue) on main thread, or you don't have startup animation on presented ViewController, you can simply add empty main thread call at the end and it will also trigger RunLoop to be awake.
Objective-C
[self performSegueWithIdentifier:@"showDetail" sender:self];
dispatch_async(dispatch_get_main_queue(), ^{});
Swift
self.performSegue(withIdentifier: "showDetail", sender: self)
DispatchQueue.main.async {}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With