模态转场需要 2 次点击而不是一次

Posted

技术标签:

【中文标题】模态转场需要 2 次点击而不是一次【英文标题】:Modal segue needs 2 clicks instead of one 【发布时间】:2013-10-29 06:59:17 【问题描述】:

我的 UITableView 需要点击 2 次才能显示所选单元格的详细信息页面:一次用于选择,另一次用于显示详细信息视图。我希望一个 clic 直接显示单击单元格的详细视图。

我在我的 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];
    

我无法使用 push segue,因为我没有导航控制器(也不想这样做)。

我查看了 TableView 属性检查器,但没有找到与此相关的任何内容。我选择了“单选”并选中了“触摸时显示选择”。 我不知道这是否可行,如果可以,在哪里看..

感谢您的帮助。


编辑 1:当我编写这样的两种方法时,它仍然不起作用(需要点击 2 次)并且我有一个新的警告日志:

“警告:尝试呈现 TCDetailViewController: 0xa27b900 on TCRootViewController: 0xa24f050 正在进行演示!"

- (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];
    


编辑 2:我不知道为什么,但有时它可以完美运行,不需要再次单击表格视图。查不出来:/


以下解决方案

【问题讨论】:

尝试,在索引路径选择行 - 然后从那里继续。 【参考方案1】:

我很喜欢问题所在!

我在 Storyboard 上更改了一个我不应该有的参数。我希望选择单元格在单击时不显示背景突出显示颜色,但 Segue 似乎基于它可以正常工作。

如何解决: 在情节提要中,在导航器中选择您的表格视图单元格,并且不要在“选择”(属性检查器)中选择“无”选项。 “蓝色”、“灰色”或“默认”似乎效果不错。

【讨论】:

【参考方案2】:

我已经将选择属性设置为“默认”,但仍然遇到双击问题。然而,该建议确实指向了一个相关的解决方案。在 didSelectRowAtIndexPath 中,调用:

self.tableView.deselectRowAtIndexPath(indexPath, animated: false)

(显然,我使用的是 Swift。)

【讨论】:

这似乎是一个奇怪的错误,只影响当前模态 -> 交叉溶解和水平翻转。您的解决方案完美运行谢谢 这个改为self.tableView.deselectRow(at: indexPath, animated: false) 是的!这就是解决方案。您必须取消选择您选择的行。故事板中的选择选项不会影响这一点。谢谢。 @Tom 对我来说,即使没有转场,它也会出现,例如:let vc = self.storyboard?.instantiateViewController(withIdentifier: "SomeController") as! SomeControllerpresent(vc, animated: true, completion: nil)【参考方案3】:

我认为解决此问题的更正确方法是在主线程上执行任何操作,在您的情况下触发 segue:

Objective-C

dispatch_async(dispatch_get_main_queue(), ^
    [self performSegueWithIdentifier:@"showDetail" sender:self];
);

斯威夫特

DispatchQueue.main.async 
    self.performSegue(withIdentifier: "showDetail", sender: self)

这实际上是一个bug,与主RunLoop和tableViewCell有关,而selectionStyles强制RunLoop唤醒(因为它必须处理动画),如果你没有selectionStyle,加上你不做任何启动动画在你呈现的 viewController 中,RunLoop 有时会进入休眠状态。

如果您出于某种原因不想在主线程上执行操作(在您的情况下它会触发 segue),或者您在呈现的 ViewController 上没有启动动画,您可以简单地添加空主线程最后调用,它也会触发 RunLoop 被唤醒。

Objective-C

[self performSegueWithIdentifier:@"showDetail" sender:self];
dispatch_async(dispatch_get_main_queue(), ^);

斯威夫特

self.performSegue(withIdentifier: "showDetail", sender: self)
DispatchQueue.main.async 

【讨论】:

【参考方案4】:

一个适合我的解决方案 (XCode 9.2) 并且看起来很简单,但仍然允许 None 选择是:

正如@Tulleb 所说,在情节提要中使用None 以外的任何内容作为Table View Cell“选择”,然后在代码中将其设置为.none

比如像这样……

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 

    let cell = tv.dequeueReusableCell(withIdentifier: "cell")
    cell?.selectionStyle = .none  // This is the important line

【讨论】:

【参考方案5】:

使用

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

而不是

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

然后你可以编写任何代码,第一次点击就可以工作。

【讨论】:

问题似乎出在其他地方。也许在故事板中。找不到...我的 segue 已经由 Storyboard 执行过一次,但它需要 2 次点击而不是 75% 的时间(在我的表格视图上)。有时它工作得很好:/【参考方案6】:

仅供参考。直到现在,使用 Xcode 8.2.1 和 Swift 3.x,我自定义的 UICollectionViewCell 子类也存在这个问题(但我想重现这个问题不需要子类。我没有时间测试这个案例。)。

我将问题总结为:点击之前选择的单元格会消耗点击事件导致取消选择,而不是预期触发选择segues。

因此解决方案是,要么不使用选择转场,而是使用编程触发转场,或者在触发选择转场时取消选择单元格本身。

【讨论】:

以上是关于模态转场需要 2 次点击而不是一次的主要内容,如果未能解决你的问题,请参考以下文章

自定义模态视图的转场动画

为什么cytoscape节点需要两个水龙头而不是一个来触发点击事件

如何解除模态转场,然后将转场推入新的视图控制器

Bootstrap:模态而不是模态[重复]

触发时第一次模态segue慢

使用模态转场时没有动画