将 UITableViewCell 中的 segue 推送到 Swift 中的 ViewController

Push segue from UITableViewCell to ViewController in Swift

我的 UITableViewCells 遇到了问题。我将我的 UITableView 连接到 API 以填充我的单元格。

然后我创建了一个函数,它获取 indexPath.row 来识别应该发送到 RestaurantViewController 的数组中的哪个 JSON-对象。

Link to my Xcode Project for easier debugging and problem-solving

下面是我的小代码片段如何将 "row-clicks" 设置为全局变量。

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
     i = indexPath.row
}

这是我的 prepareForSegue() 函数,它应该将我的 push-segue 连接到 RestaurantViewController

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
    if segue.identifier == "toRestaurant"{
    let navigationController = segue.destinationViewController as UINavigationController
    let vc = navigationController.topViewController as RestaurantViewController
    vc.data = currentResponse[i] as NSArray
 }
}

下面是我从 UITableViewCell 设置 segue 的方法

这是我的结果,我尝试单击这些单元格中的每一个,但我不会被推送到另一个单元格 viewController...我也没有收到错误。这里有什么问题?

Tried solutions that won't work

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
        if segue.identifier == "toRestaurant"{
            let vc = segue.destinationViewController as RestaurantViewController
            //let vc = navigationController.topViewController as RestaurantViewController
            vc.data = currentResponse[i] as NSArray
        }
    }

尝试在您的 cellForRow 方法中创建这样的单元格:

let cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier("MyTestCell", forIndexPath: indexPath)

我注意到在你的故事板截图中,segue 正在将第一个原型单元格连接到 RestaurantViewController。这个原型单元格看起来像是 "Basic" 风格的单元格,右边有一个披露指示器附件。但是看看你的应用程序的屏幕截图 运行。 table 填充的单元格似乎是 "Subtitle" 样式的单元格,右侧没有披露指示器附件。

无论您做什么,您的 segue 都不会触发的原因是 segue 仅配置为适用于特定的原型单元格,但是当您填充 table 时从未使用该原型单元格.无论您在 tableView:cellForRowAtIndexPath: 中做什么,您都没有使用您想要的原型单元格。

@Starscream 的想法是正确的,即使用正确的标识符将正确的单元格出队,并将其与 Interface Builder 中原型单元格的标识符相匹配。这样做之后你遇到的崩溃可能是因为上面评论中提到的先前问题。你在情节提要中的 segue 显然指向 UITableViewControllerprepareForSegue:sender: 中的代码应该是 let vc = segue.destinationViewController as RestaurantViewController,只要 RestaurantViewControllerUITableViewController 的子 class。如果您尝试将其转换为 UINavigationController,您将会崩溃。还要确保 Storyboard 中目标 UITableViewController 的 class 在 Identity Inspector 窗格中列为 RestaurantController。如果您的程序编译时认为故事板只包含一个通用的 UITableViewController ,您将会崩溃。

再回到最初的问题,我不知道你是如何实现的tableView:cellForRowAtIndexPath:,这可能很关键。也许不是那么简单。也许您计划在运行时处理许多原型单元或生成自定义单元。在这种情况下,一种简化此操作的方法是在用户点击单元格时以编程方式执行转场。不使用特定的原型单元,而是使 segue 成为从 "Restauranger nära mig" UITableViewControllerRestaurantViewController 的连接。 (通过从第一个顶部的 Table View Controller 图标拖动到第二个主体,在 Interface Builder 中连接)。您必须在 Attributes Inspector 窗格中为这个 segue 提供一个标识符,以使其有用。假设它是 "toRestaurant"。然后在 tableView:didSelectRowAtIndexPath: 方法的末尾,放入这行代码:self.performSegueWithIdentifier("toRestaurant", sender: self)。现在无论在 table 中选择了哪个单元格,这个 segue 都会为你触发。

Dropbox link to stack3 directory

  1. 我很难理解为什么您的软件与标准的 2 级 table 视图结构有很大不同。所以我编写了一个简短的示例,您可以从这个 link 访问它。我还在下面包含了源代码。

  2. 该程序模仿您所拥有的(据我所知)。 Table 控制器 1 从 table 视图单元格转到 Table 控制器 2。我对 segue-ing 没有任何问题。请注意,我没有也不需要扩充 Storybook 来启动 segue。

  3. 我已将这两个控制器嵌入到导航控制器中。我的经验是省了很多设置导航的功夫

  4. 或者,我可以通过控制从屏幕顶部的第一个 TableViewController 符号拖动到第二个控制器并设置 segue。

  5. 我使用了全局变量 (selectedRow),但不推荐这样做。但是您可以轻松地使用 prepareForSegue 在 RestaurantTableViewController 中设置变量(我展示了一个示例)

    1. 最后,我建议检查连接检查器(针对第一个控制器中的 table 视图单元格)以确认第二个控制器有一个 segue。如果您正确地控制拖动,应该会出现确认提示以及连接检查器中的条目。

不幸的是我无法正确格式化代码

import UIKit

var selectedRow = -1

class TableViewController: UITableViewController {

var firstArray = ["Item1","Item2","Item3","Item4"]

override func viewDidLoad() {

super.viewDidLoad()

}

override func didReceiveMemoryWarning() {

super.didReceiveMemoryWarning()

}

// MARK: - Table view data source

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {

return 1
}

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

return firstArray.count

}


let nameOfCell = "RestaurantCell"

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

let cell = tableView.dequeueReusableCellWithIdentifier(nameOfCell, forIndexPath: indexPath) as UITableViewCell

cell.textLabel!.text = firstArray[indexPath.row]

return cell

}

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

selectedRow = indexPath.row

}

// MARK: - Navigation

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

let vc = segue.destinationViewController as RestaurantTableViewController

// can write to variables in RestaurantTableViewController if required

vc.someVariable = selectedRow

}


}


import UIKit

class RestaurantTableViewController: UITableViewController {

var secondArray = ["Item 2.1", "Item 2.2", "Item 2.3", "Item 2.4"]

var someVariable = -1

override func viewDidLoad() {

super.viewDidLoad()

}

override func didReceiveMemoryWarning() {

super.didReceiveMemoryWarning()

}

// MARK: - Table view data source

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {

return 1

}

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

return secondArray.count

}

let nameOfCell = "RestaurantCell"

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

let cell = tableView.dequeueReusableCellWithIdentifier(nameOfCell, forIndexPath: indexPath) as UITableViewCell

cell.textLabel!.text = secondArray[indexPath.row]

if indexPath.row == selectedRow {

cell.textLabel!.text = cell.textLabel!.text! + " SELECTED"

}

return cell

}

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

selectedRow = indexPath.row

}

}

我一时兴起来这里,因为我现在才刚刚进入 swift,但我在 prepareForSegue() 中的做法是这样的:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
    if segue.identifier == "toRestaurant"{
        let navigationController = segue.destinationViewController as UINavigationController
        let vc = navigationController.topViewController as RestaurantViewController
        //notice I changed [i] to [index!.row]
        vc.data = currentResponse[index!.row] as NSArray
     }
    }

在我看来,您正在调用 i 变量,它有点像 class 方法中的私有变量。您可以像@Syed Tariq 那样对 selectRow 变量进行操作,并将其设置在您的 class SomeController: UIViewController /*, maybe some more here? */ { 之上,然后在您的

中对变量进行签名
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

    selectedRow = indexPath.row

}

方法同上,但两种方法都应该很好用。

以下步骤应该可以解决您的问题。如果没有,请告诉我。

  1. 删除您的 tableView(tableView, didSelectRowAtIndexPath:) 实现。

  2. 使 RestaurantViewController 上的 data 具有类型 NSDictionary!

  3. 确定prepareForSegue中选中的行:

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
        if let cell = sender as? UITableViewCell {
            let i = tableView.indexPathForCell(cell)!.row
            if segue.identifier == "toRestaurant" {
                let vc = segue.destinationViewController as RestaurantViewController
                vc.data = currentResponse[i] as NSDictionary
            }
        }
    }
    

问题是您没有正确处理数据。 如果您查看 currentResponse 数组,您会发现它包含 NSDictionaries,但在您的 prepareForSegue 中,您尝试将 NSDictionary 转换为 NSArray,这会使应用程序崩溃。

RestaurantViewController 中的 data 变量更改为 NSDictionary 并将您的 prepareForSegue 更改为传递 NSDictionary

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
    if let cell = sender as? UITableViewCell {
        let i = redditListTableView.indexPathForCell(cell)!.row
        if segue.identifier == "toRestaurant" {
            let vc = segue.destinationViewController as RestaurantViewController
            vc.data = currentResponse[i] as NSDictionary
        }
    }
}  

对于Swift 5

func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
        if let cell = sender as? UITableViewCell {
            let i = self.tableView.indexPath(for: cell)!.row
            if segue.identifier == "toRestaurant" {
                let vc = segue.destination as! RestaurantViewController
                vc.data = currentResponse[i] as NSDictionary
            }
        }
    }

我遇到了同样的问题,我发现解决方案是:

performSegueWithIdentifier("toViewDetails", sender: self)

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    var cellnumber = procMgr.processos[indexPath.row].numero
    println("You selected cell #\(indexPath.row)")
    println(cellnumber)
    performSegueWithIdentifier("toViewDetails", sender: self)
}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "toViewDetails" {
         let DestViewController : ViewDetails = segue.destinationViewController as! ViewDetails
    }
}

您可能需要获取 UItableview 的选定单元格索引。下面的代码使用选定的单元格索引 (UItableview.indexPathForSelectedRow) 来获取数组的正确元素。

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
    if segue.identifier == "seguaVisitCardDetial" {
        let viewController = segue.destinationViewController as! VCVisitCardDetial
        viewController.dataThisCard =   self.listOfVisitCards[(tblCardList.indexPathForSelectedRow?.row)!]
    }
}

我也遇到过这个问题; UITableViewCell 的 segue 没有调用。 经过一番查找,我发现是因为我在“选择”字段中选择了“不选择”。