I have been reading around on various ways to perform segues. I want a push segue from a cell click. I have the segue in the storyboard, so I am not using the didSelectForRow function:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let selectedRow = self.tableView.indexPathForSelectedRow as? Int else { return }
if segue.identifier == "detail", let vc = segue.destination as? DetailViewController {
vc.playerImage = UIImageView(image: UIImage(named: "userIcon"))
vc.currentRankingLabel.text = String(players[selectedRow].ranking)
vc.scoreLabel.text = String("\(players[selectedRow].wins) - \(players[selectedRow].losses)")
}
}
This is what I have got at the moment. It compiles, but the cell will not react to the click!
indexPathForSelectedRow is never Int, it's IndexPath?. Delete the conditional downcast and get the row from its row property
guard let selectedPath = self.tableView.indexPathForSelectedRow else { return }
let selectedRow = selectedPath.row
if segue.identifier == "detail", let vc = segue.destination as? DetailViewController {
vc.playerImage = UIImageView(image: UIImage(named: "userIcon"))
vc.currentRankingLabel.text = String(players[selectedRow].ranking)
vc.scoreLabel.text = String("\(players[selectedRow].wins) - \(players[selectedRow].losses)")
}
However if the segue is connected to the cell I recommend to use the sender parameter which represents the cell
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "detail", let vc = segue.destination as? DetailViewController {
let selectedPath = self.tableView.indexPath(for: sender as! UITableViewCell)!
let selectedRow = selectedPath.row
vc.playerImage = UIImageView(image: UIImage(named: "userIcon"))
vc.currentRankingLabel.text = String(players[selectedRow].ranking)
vc.scoreLabel.text = String("\(players[selectedRow].wins) - \(players[selectedRow].losses)")
}
}
Important note:
Be aware that the outlets in the destination controller are not connected in prepare(for so nothing will be displayed or the code even crashes.
I think you need call performSegue on cell selection, like below
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.performSegue(withIdentifier: "detail", sender: indexPath)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let selectedPath = sender as? IndexPath, let selectedRow = selectedPath.row, let player = players[selectedRow] else {
return
}
if segue.identifier == "detail", let vc = segue.destination as? DetailViewController {
vc.playerImage = UIImageView(image: UIImage(named: "userIcon"))
vc.currentRankingLabel.text = String(player.ranking)
vc.scoreLabel.text = String("\(player.wins) - \(player.losses)")
}
}
Related
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.selectedIndexPath = indexPath as NSIndexPath
performSegue(withIdentifier: "toAddToChart", sender: nil)
}
open override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let indexPath = self.selectedIndexPath
let product = products[indexPath.row]
if (segue.identifier == "toAddToChart") {
if let viewController = segue.destination as? AddToOrderVC {
viewController.productName = product.productName
viewController.productCode = product.productCode
viewController.productType = product.productType
viewController.productPrice = product.productPrice
viewController.productDetails = product.productDescription
viewController.pImageUrl = product.productimageUrl
}
}
}
/when i remove prepareForSegue function from viweController its will work but when i apply it and after build the code i get thread 1:signal SigBArt error when another action segue button pressed
When let product = products[indexPath.row]
called out side of the segue with confirm identifier,it will beget an error so the of this error is
open override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let indexPath = self.selectedIndexPath
if (segue.identifier == "toAddToChart") {
if let viewController = segue.destination as? AddToOrderVC {
let product = products[indexPath.row]
viewController.productName = product.productName
viewController.productCode = product.productCode
viewController.productType = product.productType
viewController.productPrice = product.productPrice
viewController.productDetails = product.productDescription
viewController.pImageUrl = product.productimageUrl
}
}
}
I can list datas in tableview. When I choose a row and trying to pass another view controller with showing specific data related to my pressed cell, It couldn't make it.
I didn't able to store data "selectedMeal" variable in prepareforsegue function, it always return [ ].
I think, my main problem is selecting the cell and sending to this cell to prepare for segue function. Perhaps, it has a problem in DispatchQueue.main.async function.
*When I try to pass to static data, it works great.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) {
cell.accessoryType = .checkmark;
DispatchQueue.main.async {
self.performSegue(withIdentifier: "gotoOrderDetail", sender: self)
}
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "gotoOrderDetail") {
let DestViewController : OrderDetailListViewController = segue.destination as! OrderDetailListViewController
let selectedMeal = selectedCells.map { (index: Int) -> SavedMeal in
return savedMeal[index]
}
DestViewController.mealarray = selectedMeal
}
}
Try to use this code
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "gotoOrderDetail") {
let DestViewController : OrderDetailListViewController = segue.destination as! OrderDetailListViewController
let path = self.tableView.indexPathForSelectedRow()! // get the selected indexPath
DestViewController.mealarray = savedMeal[path.row]
}
}
Try to use Sender parameter
you can you like this:
self.performSegue(withIdentifier: "gotoOrderDetail", sender: indexPath)
and then in prepare(for segue: sender?)
if (segue.identifier == "gotoOrderDetail") {
let DestViewController : OrderDetailListViewController = segue.destination as! OrderDetailListViewController
let index = sender as! Int
DestViewController.mealarray = savedMeal[index]
}
p/s: you do not need to use dispatch queue in this case
I'm trying to segue and pass data (from UITableView to a UIViewController). My code is
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "IndividualAchievementsSegue" {
let destination = segue.destinationViewController as? IndividualAchievementsViewController
let cell = sender as! UITableViewCell
let selectedRow = AchievementsTable.indexPathForCell(cell)!.row
destination!.viaSegue = achievements[selectedRow]
print(selectedRow)
}
}
but the line let cell = sender as! UITableViewCell is throwing
Could not cast value of type 'ProgramName.AchievementsViewController' to 'UITableViewCell'
I have also tried
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "IndividualAchievementsSegue" {
let destination = segue.destinationViewController as? IndividualAchievementsViewController
let selectedRow = AchievementsTable.indexPathForSelectedRow!.row
destination!.viaSegue = achievements[selectedRow]
print(selectedRow)
}
}
That fails because it finds nil unwrapping the optional during achievements[selectedRow] since that apparently gives me a nil from let selectedRow = AchievementsTable.indexPathForSelectedRow!.row
I think the problem is that your segue is connected with your AchievementsViewController to IndividualAchievementsViewController instead of UITableViewCell to IndividualAchievementsViewController. Check in the storyboard for that and correct the segue with TableCell to IndividualAchievementsViewController.
So the solution was to go into DidSelectrowAtIndexPath and remove DeselectRowAtIndexPath, which was in there twice by accident. Then use the following
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "IndividualAchievementsSegue" {
let destination = segue.destinationViewController as? IndividualAchievementsViewController
let selectedRow = AchievementsTable.indexPathForSelectedRow?.row
destination!.viaSegue = achievements[selectedRow!]
print(selectedRow)
}
}
I am creating a slide menu for ios but I'm having problems
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let DestVC = segue.destinationViewController as ViewController
let indexPath : NSIndexPath = self.tableView.indexPathForSelectedRow()!
DestVC.varView = indexPath.row
}
why doesn't this code work?
You need to make optional cast cause segue.destinationViewController is UIViewController that can't be always casted to its subclass
Try this
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
guard let DestVC = segue.destinationViewController as? ViewController else { return }
let indexPath : NSIndexPath = self.tableView.indexPathForSelectedRow()!
DestVC.varView = indexPath.row
}
When I segue my UIImageView from my NewsTableViewController.swift, the image does not appear in my NewsDetailTableViewController.swift.
Here is an image of my simulator:
Here is an image of my Main.storyboard:
Here is my prepareForSegue() method code:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?){
if segue.identifier == "showDetail" {
if let indexPath = tableView.indexPathForSelectedRow {
let destinationController = segue.destinationViewController as! NewsDetailTableViewController
destinationController.item = items[indexPath.row]
let newsImage = UIImageView(image: UIImage(named: detailImages[indexPath.row]))
destinationController.image = newsImage
}
}
}
It is also worth mentioning that my image in my NewsTableViewController.swift is set to 0x0, and in my NewsDetailTableViewController.swift, it is set to 600x216. I don't know if this would matter or not. If you desire any code, please do feel free to ask.
FYI, I use Swift.
In prepareForSegue the IBOutlets of your destinationController have not been initialized yet. Just pass detailImages to another array property on NewsDetailTableViewController. Change your prepareForSegue to:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?){
if segue.identifier == "showDetail" {
if let indexPath = tableView.indexPathForSelectedRow {
let destinationController = segue.destinationViewController as! NewsDetailTableViewController
destinationController.item = items[indexPath.row]
destinationController.imageNames = detailImages
}
}
}
Then in NewsTableViewController add the following code:
var imageNames:[String]?
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//replace with whatever identifier you're using
var cell:UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("Cell") as UITableViewCell
cell.imageView?.image = self.imageNames[indexPath.row]?
return cell
}