Modal segue needs 2 clicks instead of one

一世执手 提交于 2019-12-04 18:34:25

问题


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


回答1:


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.




回答2:


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.)




回答3:


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



回答4:


Use

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

instead of

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender

Then you can write any code and it works on the first click.




回答5:


FYI. until now, with Xcode 8.2.1 and Swift 3.x, the issue also exists for my customized UICollectionViewCell subclass (But I suppose subclass is not needed to reproduce this issue. I have no time to test this case.).

I summarize the issue as: tapping on the previously selected cell will consume the tap event to cause deselection, instead of expectedly triggering the selection segues.

So the solution is to, either not use the selection segues, say, but use programmatically triggering segues, or deselect the cell itself whenever a selection segue is triggered.




回答6:


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 {}


来源:https://stackoverflow.com/questions/19483441/modal-segue-needs-2-clicks-instead-of-one

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!