I need to override a segue function after clicking a - ios

So I have this tableView and I want when clicking a cell it gives me the name of that cell, and I pass it to next view, but the problem is that I need to override segue function inside of the "didselectrowAt" function and that is impossible I guess, any suggestion on how to do this?
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
clickedYear = years[indexPath.row]
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let ResumosVC: Resumos2ViewController = segue.destination as! Resumos2ViewController
ResumosVC.Title = clickedYear
}

Two solutions:
Reconnect the segue to the cell (rather than to the controller) and implement
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let cell = sender as? UITableViewCell,
let indexPath = tableView.indexPath(for: cell) else { return }
let resumosVC = segue.destination as! Resumos2ViewController
resumosVC.Title = years[indexPath.row]
}
Call performSegue in didSelect (replace the identifier string with the real value)
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "MySegueIdentifier", sender: indexPath)
}
and change prepare(for to
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let indexPath = sender as? IndexPath else { return }
let resumosVC = segue.destination as! Resumos2ViewController
resumosVC.Title = years[indexPath.row]
}
clickedYear is not needed in both cases.
Note: Please conform to the naming convention to name variables with starting lowercase letter.

Related

Pass var from selected TableView Cell Swift Xcode

I'm a beginner in Swift (Xcode) and I need help. I have a tableview and I want to send information from the indexPath.row to a segue.
My script work, but the problem is the data send to my segue is the previous selected row and not the current cell select. Because the function prepare segue is called before the func tableView. That's make 2 days I search and every tutorial give me the same problem.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
jobname = filldata[indexPath.row]
print(jobname)
performSegue(withIdentifier: "jobsegue", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "jobsegue" {
let destVC = segue.destination as! JobNameViewController
destVC.jobname = jobname
}
}
Thank you sooo much for your help!
Try this, this will work fine:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "jobsegue", sender: indexPath.row)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "jobsegue" {
let destVC = segue.destination as! JobNameViewController
destVC.jobname = filldata[sender]
}
}

Prepare for segue inside of for loop

I have a table view with the following willSelectRowAt code:
func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
for n in 0...carsArray.count - 1 {
if indexPath.row == n {
print(carsArray[n].name)
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToEditCar" {
let name = carsArray[n].name
print(name)
let indexCar = n
let destinationVC = segue.destination as! EditCarViewController
destinationVC.name = name
destinationVC.indexCar = indexCar
}
}
performSegue(withIdentifier: "goToEditCar", sender: self)
}
}
}
Somehow the prepare function won't pass the desired data, neither will it print(name) - can anyone tell me the issue with this piece of code?
Your code cannot work at all. You are using the wrong API, prepare(for is never going to be called inside another method and actually you don't need a loop.
willSelectRowAt is to control if a cell is allowed to be selected. Return the indexPath if it's allowed otherwise return nil
This is not what you want. Use didSelect and pass the index path as sender when calling performSegue
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "goToEditCar", sender: indexPath)
}
In prepare(for get the index path from the sender parameter
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToEditCar" {
let indexPath = sender as! IndexPath
let name = carsArray[indexPath.row].name
print(name)
let destinationVC = segue.destination as! EditCarViewController
destinationVC.name = name
destinationVC.indexCar = indexPath.row
}
}
You don't need a for-loop here as n eventually will be equal to indexPath.row also you should use didSelectRowAt
func tableView(_ tableView: UITableView,didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "goToEditCar", sender:indexPath.row)
}
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToEditCar" {
let index = sender as! Int
let destinationVC = segue.destination as! EditCarViewController
destinationVC.name = carsArray[index].name
destinationVC.indexCar = index
}
}

Swift 4.2 - How to call "indexPath.row" from "didSelectRowAtIndexPath" method in a tableView to another class?

I have two viewControllers. One has a tableView which has some cells from an array; And the other is a viewController which contains a webkit that I want to present some local HTML files. Also I defined the webKit page as tableView's next page.
What I want is, when a user chooses a cell in the tableView, according to which cell is selected, it goes to webkit Page, and some parts of codes runs for user to show a specific HTML. In other words, I have 5 HTML files and 5 items in tableViewCells
so if a user chooses for example the first item, the HTML1 shows to him, if he chooses the second cell, the HTML2 present for him etc.
I tried a lot of ways. but nothing happened. also tried to create instance object from the tableview class...
tried also some same problem here ins StackOverFlow but not succeed
First Page:
var arr = ["masoud" , "hossein", "reza" , "shiva" , "fateme"]
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("item selected is : \(indexPath.row)")
// if indexPath.row == 1 {
performSegue(withIdentifier: "TableSegue", sender: nil)
//}
tableView.deselectRow(at: indexPath, animated: true)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
switch (segue.destination.view, segue.destination, sender) {
case let (_, controller as WebKitController, indexPath as NSIndexPath):
controller.indexPath = indexPath
break
default:
break
}
}
the Second Page:
import WebKit
class WebKitController: UIViewController, WKUIDelegate, WKNavigationDelegate {
#IBOutlet weak var myWebKit: WKWebView!
var reza : String = String()
var indexPath: NSIndexPath? {
didSet {
reza = (indexPath?.row.description)!
print(indexPath?.row as Any)
self.myWebKit.uiDelegate = self
self.myWebKit.navigationDelegate = self
}
}
override func viewDidLoad() {
super.viewDidLoad()
let url = Bundle.main.url(forResource: "reza", withExtension: "html", subdirectory: "ReZeynoo2")!
myWebKit.loadFileURL(url, allowingReadAccessTo: url)
let request = URLRequest(url: url)
myWebKit.load(request)
self.myWebKit.uiDelegate = self
self.myWebKit.navigationDelegate = self
}
As an alternative approach
I would store not a simple array but struct of name and bool is selected or not
struct CellData {
let name: String!
let isSelected: Bool!
let index: Int!
init(name: String, isSelected: Bool, index: Int) {
self.name = name
self.isSelected = isSelected
self.index = index
}
}
Then in didSelectAtRow func will make selected the cell which tapped and use this info in prepare for segue func
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.deselectAll()
self.cellItems[indexPath.row].isSelected = true
performSegue(withIdentifier: "TableSegue", sender: nil)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
switch (segue.destination.view, segue.destination, sender) {
case let (_, controller as WebKitController, indexPath as NSIndexPath):
if let item = cellItems.first(where: {$0.isSelected == true}) {
controller.indexPath = item.index
}
break
default:
break
}
}
private func deselectAll() {
for item in cellItems {
item.isSelected = false
}
}
You need to create a Int variable in WebKitController class as selectedRow where the selected row will get assigned from table view cell selection,
// MARK: - Table view delegates
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.performSegue(withIdentifier: "TableSegue", sender: indexPath)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "TableSegue", let indexPath = sender as? IndexPath {
let webController = segue.destination as? WebKitController
webController.selectedRow = indexPath.row
}
}
I think you can pass your indexpath.row value in sender of your perfomSegue and your second view controller just use this
here is code
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "secondvc", sender: indexPath.row)
}
just send indexpath.row value in sender
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "secondvc"{
let vc = segue.destination as! SecondViewController
vc.row = sender as! Int
}
}

How to pass data from NSObject to another ViewController when click on TableViewCell?

I have a ViewController1 with a TableView inside. What I want to do is go to ViewController2 and pass a piece of data along at the same time when user click on a TableViewCell.
For more details :
Each Cell have a itemId and other data which is store in NSObject class after pull from my API,which I use the data in TableViewCell class.So when I performSegue to ViewController2,I want to get the itemId in ViewController2
For now I able to go to ViewController2 when click on a tableViewCell by using this code:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
//here I dont know how to get the itemId for that particular cell
performSegue(withIdentifier: "GoToSecondVc", sender: self)
}
I know I can pass my itemId like this:
var itemId : Int!
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "GoToSecondVc" , let secondVC = segue.destination as? SecondViewController{
secondVC.itemId = self.itemId
}
The problem for now is I dont know how to get the itemId from NSObject when user click on any tableViewCell before I performSegue in didSelectRowAt section.
So how can I get the itemId in this case? Or is there a better way to do this?
I recommend to pass the selected index path in didSelectRowAt as sender:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "GoToSecondVc", sender: indexPath)
}
And use it in prepare(for segue, a temporary variable itemId is not needed. The code assumes that items is the data source array:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "GoToSecondVc" , let secondVC = segue.destination as? SecondViewController {
let indexPath = sender as! IndexPath
let item = items[indexPath.row]
secondVC.itemId = item.itemId
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let it = dataArrray[indexPath.row] as! ItemType
performSegue(withIdentifier: "GoToSecondVc", sender: it.itemID)
}

Swift/XCode - Why can't I pass data to the next view controller when a tableViewCell is pressed?

Apologies if this has already been answered elsewhere- I have spent the last two hours trying different things using similar suggestions but I still can't solve it!
Basically, I have a UITableView with custom cells(for different quiz topics) that when pressed, should allow the app to go to the next VC and pass an integer so the next VC knows which quiz to load. In my table view VC I have this:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
rowPressed = indexPath.row
print ("rowPressed = \(rowPressed) before VC changes")
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.destination is GameVC {
let vc = segue.destination as? GameVC
vc?.toPass = rowPressed
print("I ran...")
} else {
print("You suck")
}
and in my GameVC I have this:
var toPass = Int()
override func viewDidLoad() {
super.viewDidLoad()
print("toPass = \(toPass)")
The console output when run is this:
I ran...
toPass = 0
rowPressed = 3 before VC changes
So it looks like the VC changes before the previous one can send the correct value of toPass. How do I fix this?
Many thanks in advance!
According to the segue description:
For example, if the segue originated from a table view, the sender parameter would identify the table view cell that the user tapped.
So, sender is a UITableViewCell and you can do like below:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let cell = sender as? UITableViewCell else { return }
guard let idx = tableView.indexPath(for: cell) else { return }
guard let vc = segue.destination as? GameVC else { return }
vc.toPass = idx.row
}
The problem of your code was prepare(segue:) was invoked before tableView(didSelectRowAt:).
As suggested you have to call the performSegue method:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// not necessary
//rowPressed = indexPath.row
//print ("rowPressed = \(rowPressed) before VC changes")
performSegueWithIdentifier("Your id", sender: indexPath)
//You can set the identifier in the storyboard, by clicking on the segue
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "Your id"{
var vc = segue.destinationViewController as! GameVC
vc.toPass = (sender as! IndexPath).row
}
}
Because prepareForSegue is called before didSelectRowAt, you can also remove the segue from the Storyboard, drag and drop holding ctrl from the UITableViewController's yellow icon in the top to the second ViewController, click on the segue, give it an identifier, so now you can call performSegue:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.pressed = indexPath.row
self.performSegue(withIdentifier: "segue identifier", sender: nil)
}

Resources