TableView 在 Swift 中推送到详细视图

Posted

技术标签:

【中文标题】TableView 在 Swift 中推送到详细视图【英文标题】:TableView Pushing to Detail View in Swift 【发布时间】:2014-11-17 21:00:26 【问题描述】:

我需要帮助将我的 tableView 推送到 detailView。现在我有大部分代码,但是当我的应用程序加载时,它会转到detailedView,每当我尝试返回tableView时,它会立即返回detailedView,并且在调试区域中显示以下错误:

在意外状态下完成导航转换。导航栏子视图树可能已损坏。

我不明白为什么会这样,因为我的代码不在代码的 viewDidLoad 部分中...这是我的 tableView 代码:

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int 

    return Label.count



func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 

    var cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")

    cell.textLabel.text = Label[indexPath.row]

    performSegueWithIdentifier ("showDetail", sender: self)
    func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) 

        if segue.identifier == "showDetail" 


        

    

    return cell


如果您可以帮助我使我的 segue 按预期工作,请在下面留下答案。谢谢!

附:我也很好奇如何将导航栏上的后退按钮从“

附言如何使 tableViewCell 在按下后自动释放,使其不会保持突出显示?只是它看起来像一个整体上更好的应用程序。

P.S.S.S 抱歉,最后一件事是如何根据用户单击的单元格自定义 DeatilView?我已经用文本设置了新类,但不知道如何制作为每个单击的单元格自定义文本的 if 语句。

再次感谢!

【问题讨论】:

您一次只能问一个问题。 【参考方案1】:

错误在你的cellForRowAtIndexPath:

performSegueWithIdentifier ("showDetail", sender: self)

这会在显示单元格时触发 segue,而不是在选中单元格时触发。解决这个问题的最简单方法是在 IB 中创建一个从单元到目标视图控制器的 segue。

另外,这段代码:

func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) 
    if segue.identifier == "showDetail" 
        

创建一个永远不会执行的cellForRowAtIndexPath 本地函数。正确的方法是在类作用域中声明它作为超类实现的覆盖。

如果你已经在 IB 中定义了一个 segue,那么你的代码应该是这样的:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 
    var cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
    cell.textLabel.text = Label[indexPath.row]
    return cell


override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) 
    if segue.identifier == "showDetail" 

    

【讨论】:

我在 IB 中有一个名为 showDetail 的 segue,但仍然出现此错误。你建议我改变什么?我不明白你建议我改变什么,对不起。你能告诉我使用什么代码吗?如果有帮助,我也会收到此错误:嵌套推送动画可能导致导航栏损坏【参考方案2】:

你必须在tableView(_:didSelectRowAtIndexPath:) 中执行转场而不是 tableView(_:cellForRowAtIndexPath:)

【讨论】:

现在可以使用了!非常感谢!很抱歉很痛苦,但是您知道如何解决我在 P.S 和 P.S.S 中所说的问题吗?以及如何根据用户点击的单元格自定义DetailedView?我知道如何在 ObjC 中做到这一点,但尝试在 Swift 中学习。 (我刚刚也将其添加到原始问题中)【参考方案3】:

附注如何将导航栏上的后退按钮从“

我发现这个老问题在 Objective C 中有答案,How to change text on a back button

您必须在您要从中进行切换的视图控制器中进行设置。

假设我们有一个简单的 iPhone 应用程序,它有一个 UITableViewController 和一堆列出数字的单元格,我们称之为“NumberListTVC”。我们将此 NumberListTVC 嵌入到 NavigationController 中。我们将其中一个单元格上的选择序列设置为另一个 ViewController,我们将其称为“NumberDisplayerVC”。这个 NumberDisplayerVC 有一个标签,我们将把它设置为在 NumberList 上单击的标签的内容。因此,当您在 NumberListTVC 中选择一个单元格时,它将推送到 NavigationController 中的“NumberDisplayer”。

所以对于这个应用程序,您可以将自定义后退按钮的代码放在 NumberListTVC 中,这样当您查看 NumberDisplayerVC 时,它会显示我们想要的后退按钮,而不是默认按钮(因为后退按钮将其带回 NumberListTVC)。

在 Objective-C 中,根据链接的答案,将“

self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];

基本上,我们创建了一个新的 UIBarButtonItem ,它具有我们想要的任何标题。在这种情况下,我只是给它的标题“”,它只是一个空字符串。

在 Swift 中同样的命令是:

self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style:.Plain, target: nil, action: nil)

我把它放在 NumberListTVC 的 viewDidLoad 方法中,以确保它在 NumberListTVC 加载时运行。

附言如何让 tableViewCell 在按下后自动释放,使其不会保持突出显示?

这在 Objective-C 中的答案 Selected UItableViewCell staying blue when selected 中有介绍

您只需告诉 UITableViewCell 在其 didSelectRowAtIndexPath 中取消选择它。

在 Objective-C 中,您可以覆盖它并执行以下操作: - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath //在这里做任何你想做的事情... [tableView deselectRowAtIndexPath:indexPath 动画:YES];

Swift 代码类似:

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)

    //Do whatever else you want to do here...

    tableView.deselectRowAtIndexPath(indexPath, animated: true)

P.S.S.S 如何根据用户单击的单元格自定义 DetailView?

为简单起见,我将使用我的第一个示例,它只是将我们的 navigationController 与 NumberListTVC 和 NumberDisplayerVC 一起使用,因此不在 UISplitView 上,但提出的问题会影响这两种情况。

基本上,你必须从被点击的单元格中获取你想要的东西,然后将它设置为你想要在下一个 ViewController 中使用的任何东西。因此,在您的 prepareForSegue 中,您将执行以下操作:

if segue.identifier == "amazingSegue"

    if let cellText = (sender as? UITableViewCell)?.textLabel.text
    
        if let someVC = segue.destinationViewController as? NumberDisplayerVC
        
            someVC.textToDisplay = cellText
        
    

这基本上是安东尼奥在his answer 中所说的。我加了一点。所以在我的例子中,NumberListTVC 是一堆动态创建的 UITableViewCells。我想从每个标签中取出标签,然后在 NumberDisplayerVC 中使用它。所以我们:

    检查它是否是我们想要实际使用的segue,在这种情况下,NumberListTVC 和 NumberDisplayerVC 之间的 segue 被命名为“amazing segue”。 接下来,使用可选绑定将发送方单元格的文本分配给常量cellText。我们使用可选的类型转换运算符来检查发送者是否是 UITableViewCell。然后,我们使用可选链查看此 UITableViewCell 内部并从其textLabel 中提取text。 再次使用可选绑定将我们的destinationViewController 分配给常量someVC。我们可以选择将其类型转换为 NumberDisplayerVC,这就是它应该的样子。如果它确实是 1,它将正确绑定到 someVC 变量。 然后只需将textToDisplay 属性设置为我们之前可选绑定的cellText 常量。

我不确定这是否是最好的方法,我对 if let 语句的塔感觉不太好,但它最初可以完成工作。

【讨论】:

以上是关于TableView 在 Swift 中推送到详细视图的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Angular 4 中推送到数组的 Observable? RxJS

如何在 React Router v5 中推送到历史记录?

如何在 React Router v5 中推送到历史记录?

我可以在 git 的一个命令中推送到多个存储库吗?

从 Vue.js 2 中的计算属性中推送到数组

在 mongodb 的一次更新调用中推送到两个单独的数组