模态转场需要 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! SomeController
present(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 次点击而不是一次的主要内容,如果未能解决你的问题,请参考以下文章