可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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 {}