在Swift中从UITableViewCell中将Segue推到ViewController
我遇到了我的UITableViewCells的问题。 我连接我的UITableView到一个API来填充我的单元格。
然后我创build了一个抓取indexPath.row
的函数来确定应该发送到RestaurantViewController
的数组内的哪个JSON对象。
链接到我的Xcode项目,更容易debugging和解决问题
以下是我的小片段将“行 – 点击”设置为全局variables的方式。
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 …我也没有得到一个错误。 这里有什么问题?
试过的解决scheme,将无法正常工作
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 } }
问题是你没有正确处理你的数据。 如果你看看你的currentResponse
数组,你会看到它拥有NSDictionaries,但在prepareForSegue
你试图将一个NSDictionary转换成一个NSArray,这会使应用程序崩溃。
将RestaurantViewController
的data
variables更改为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 } } }
以下步骤应该解决您的问题。 如果没有,请让我知道。
-
删除你的
tableView(tableView, didSelectRowAtIndexPath:)
实现。 -
使
data
在RestaurantViewController
有types的NSDictionary!
-
确定
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 } } }
Dropbox链接到stack3目录
-
我很难理解为什么你的软件与标准的2级桌面结构有很大不同。 所以我编了一个简短的例子,你可以从这个链接访问。 我还包括下面的源代码。
-
该程序模仿你有什么(尽我所知)。 表格控制器1从表格单元中跳转到表格控制器2。 我没有遇到问题。 请注意,我没有也不需要增加故事书来启动search。
-
我在导航控制器中embedded了两个控制器。 我的经验是,它节省了很多努力来设置导航。
-
或者,我可以将控件从屏幕顶部的第一个TableViewController符号拖动到第二个控制器并设置segue。
-
我使用了一个全局variables(selectedRow),尽pipe这不是一个推荐的做法。 但是,您也可以轻松使用prepareForSegue在RestaurantTableViewController中设置一个variables(我将演示一个示例)
- 最后,我build议检查Connections Inspector(对于第一个控制器中的表视图单元格)以确认第二个控制器有一个继续。 如果您控制正确拖动应该有确认提示以及连接检查器中的条目。
不幸的是我只是不能得到正确的格式化代码
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 } }
我注意到,在您的故事板的截图中,segue将第一个原型单元连接到RestaurantViewController
。 这个原型电池看起来就像是“基本”电池样式,在右边有一个披露指示器附件。 但看看你的应用程序运行的截图。 该表正在填充单元格,该单元格似乎是右侧没有披露指示器附件的“单元格”单元格样式。
不pipe你做什么,你的segue永远不会被触发的原因是segue只被configuration为为特定的原型单元格工作,但是当你填充表格时,原型单元格从来没有被使用过。 无论你在tableView:cellForRowAtIndexPath:
做什么,你都没有使用你想要的原型单元格。
@Starscream有正确的想法,使用正确的标识符将正确的单元格出列,并将其与Interface Builder中的原型单元格的标识符进行匹配。 你之后得到的这个崩溃可能是因为上面的评论中提到的上一个问题。 在故事板中的segue显然指向一个UITableViewController
。 您的代码在prepareForSegue:sender:
应该let vc = segue.destinationViewController as RestaurantViewController
,只要RestaurantViewController
是UITableViewController
的子类。 如果您尝试将其转换为UINavigationController
则会崩溃。 还要确保故事板中目标UITableViewController
的类在Identity Inspector窗格中列为RestaurantController
。 如果程序编译时认为故事板只包含一个通用的UITableViewController
,就会崩溃。
回到原来的问题更多,我不知道你是如何实现tableView:cellForRowAtIndexPath:
这可能是至关重要的。 也许这不是那么简单。 也许你计划在处理许多原型单元或在运行时生成自定义单元格。 在这种情况下,一种简单的方法是在用户点击一个单元格时编程执行segue。 而不是使用特定的原型单元格,而是将来自“Restaurangernäramig” UITableViewController
的连接发送到RestaurantViewController
。 (通过按住Control键并点击从第一个表格顶部的表格视图控制器图标拖到第二个表格的主体)来在Interface Builder中进行连接。 您必须在“属性检查器”窗格中给这个segue一个标识符以使其有用。 我们说这是"toRestaurant"
。 然后在tableView:didSelectRowAtIndexPath:
方法的末尾放上这行代码: self.performSegueWithIdentifier("toRestaurant", sender: self)
。 现在无论表格中选了什么单元格,这个segue都会为你启动。
尝试在您的cellForRow
方法中创build像这样的单元格:
let cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier("MyTestCell", forIndexPath: indexPath)
因为我现在正在快速进入,但我在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 } }
对我来说,看起来像你正在调用variables,就像你的类的一个方法中的一个私有variables。 你可以像@Syed Tariq那样做selectRow
variables,并将其设置在你的class SomeController: UIViewController /*, maybe some more here? */ {
之上class SomeController: UIViewController /*, maybe some more here? */ {
class SomeController: UIViewController /*, maybe some more here? */ {
然后在你的内部签名variables
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { selectedRow = indexPath.row }
像上面的方法,但两种方式应该工作得很好。
我有同样的问题,我发现解决scheme是:
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)!] } }