I am making a todo list app and have two View Controllers and I have to pass the Index Path of the selected row from the CategoryViewController to ItemsViewController and trigger the Segue...
This Is my Category View Controller
But when I Click one of the cell, it is just being selected but the segue is not triggered
Heres How
But the segue is triggered when I select another Cell after selecting First one...Here's My code
override func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "goToItems", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
print("sucess")
let destinationVC = segue.destination as! ToDoListViewControlorer
if let indexPath = tableView.indexPathForSelectedRow {
destinationVC.selectedCategory = categoriesArray[indexPath.row]
}
}
Send your indexPath.row in sender argument of performSegue
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
performSegue(withIdentifier: "youridentifier", sender: indexPath.row)
}
get indexPath.row from the sender argument and pass to ToDoListViewControlorer
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
print("sucess")
let destinationVC = segue.destination as! ToDoListViewControlorer
if let indexPathRow = sender as? Int {
destinationVC.selectedCategory = categoriesArray[indexPathRow]
}
}
First, override didSelectRowAt method, because you want to handle moment when user select row, not deselect. Also as sender pass selected item
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "goToItems", sender: categoriesArray[indexPath.row])
}
and then in prepare(for:sender:) just downcast sender
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destinationVC = segue.destination as? ToDoListViewControlorer {
destinationVC.selectedCategory = sender as! Category
}
}
p.s. name your controller Controller, not Controlorer
Related
I'm creating an app for a school project, and I have a tableView with a label inside which contains the name of the cell, and I am trying to pass the name of the label to the navTitle variable on my second viewController. I have tried multiple ways of achieving this but have had no luck.
I have tried printing the passed title but it prints the output 'nil'
Home view
var names = ["Accomodation", "Facilities", "Things To Do", "About"]
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return names.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "homeCell", for: indexPath) as? homeTableViewCell
cell?.label.text = names[indexPath.row]
return cell!
}
//Passing data
var nameChosen : String?
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.tableView.deselectRow(at: indexPath, animated: true)
nameChosen = names[indexPath.row]
performSegue(withIdentifier: "accomodationSegue", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let destinationVC = segue.destination as? accomodationViewController
destinationVC?.navTitle = nameChosen
}
Accomodation view
var navTitle: String?
override func viewDidLoad() {
super.viewDidLoad()
print(navTitle)
// Do any additional setup after loading the view.
}
The easiest way is to pass the name as sender parameter, the property nameChosen is not needed.
And it's good practice to check the identifier of the segue in prepare(for segue
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.tableView.deselectRow(at: indexPath, animated: true)
let name = names[indexPath.row]
performSegue(withIdentifier: "accomodationSegue", sender: name)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard segue.identifier == "accomodationSegue" else { return }
let destinationVC = segue.destination as! accomodationViewController
destinationVC.navTitle = sender as! String
}
If the code crashes you made a design mistake.
And please name classes always with starting uppercase letter (AccomodationViewController).
I want to make it so that when I tap on a CollectionView Cell, it segues to another view. I also want to pass a user ID to this view so I can query the database. This is what I have implemented so far:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionview.dequeueReusableCell(withReuseIdentifier: "userCell", for: indexPath) as! UserCell
print(user[indexPath.row].imagePath!)
cell.userImage.sd_setImage(with: URL(string: user[indexPath.row].imagePath!))
cell.nameLabel.text = user[indexPath.row].username
cell.userID = user[indexPath.row].userID
let destinationVC = ProfileViewController()
destinationVC.sentUserID = user[indexPath.row].userID!
// Let's assume that the segue name is called playerSegue
// This will perform the segue and pre-load the variable for you to use
//destinationVC.performSegue(withIdentifier: "toProfileFromSearch", sender: self)
cell.addButtonTapAction = {
// implement your logic here, e.g. call preformSegue()
self.performSegue(withIdentifier: "toProfileFromSearch", sender: self)
}
//cell.userImage.downloadImage(from: self.user[indexPath.row].imagePath!)
//checkFollowing(indexPath: indexPath)
return cell
}
This is in the individual creation of each cell. When I click the user profile in the search area, nothing happens.
I followed other stack overflow questions to get this far. Can anyone make a complete solution for other people that need this too?
You can use the didSelectItemAt function, check this
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let VC1 = self.storyboard!.instantiateViewController(withIdentifier: "IDYOURVIEW") as! ProfileViewController
VC1.sentUserID = user[indexPath.row].userID!
self.navigationController?.pushViewController(VC1, animated: true)
}
If you're using segues
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
self.performSegue(withIdentifier: "toProfileFromSearch", sender: user[indexPath.row].userID!)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if segue.identifier == "toProfileFromSearch"
{
let vc = segue.destination as? ProfileViewController
if let id = sender as! String
{
vc?.sentUserID = id
}
}
}
There is another better way to handle this using protocol
protocol UserCellTapedDelegate: AnyObject {
func didTapButton(_ cell: UserCell, didSelectItemAt id: Int)
}
then your cell would be like:
class UserCell: UICollectionViewCell {
public var userID: Int!
public weak var delegate: UserCellTapedDelegate?
#objc private func addButtonTapAction() {
delegate?.didTapButton(self, didSelectItemAt: userID)
}
}
userID: to store the user ID.
delegate: use an optional weak (in terms of memory management) delegate reference in your cell.
addButtonTapAction func to handle target of the button/or tap gesture on Any UIView.
The next step is to go back to your UIViewController and conform to the custom delegate:
extension ViewController: UserCellTapedDelegate {
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionview.dequeueReusableCell(withReuseIdentifier: "userCell", for: indexPath) as! UserCell
...
cell.userID = user[indexPath.row].userID!
cell.delegate = self
return cell
}
func didTapButton(_ cell: UserCell, didSelectItemAt id: Int) {
self.performSegue(withIdentifier: "toProfileFromSearch", sender: id)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "toProfileFromSearch" {
let vc = segue.destination as! ProfileViewController
if let id = sender as! String {
vc.sentUserID = id
}
}
}
}
Hope this helps you 😊
i have tableview which has several cells, when user tap on the cell it does some other function and when cell accessory is tapped i want it to segue to another view controller
i am able to do so but the problem is i am not able to send the data at cell indexpath row, in order to send data i first have to touch the cell then tap on accessory to send the data here is the code for tableview
func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
myTableView.selectRow(at: indexPath, animated: true, scrollPosition: .none)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
switch segue.identifier {
case "ShowDetail":
if let ip = myTableView.indexPathForSelectedRow{
if let svc = segue.destination as? DetailViewController{
svc.selectedObject = (myCounters?[ip.row])!
}
}
default:
print("error in segue")
}
}
func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
let vc = storyboard?.instantiateViewController(withIdentifier: "detailvc") as? DetailViewController
vc?.selectedObject = (myCounters?[indexPath.row])!
navigationController?.present(vc!, animated: true, completion: nil)
}
thanks to #shahzaib qureshi
i removed the segue connection and use instantiate view controller method as detail view controller in cell accessory tapped method
func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
let vc = storyboard?.instantiateViewController(withIdentifier: "detailvc") as? DetailViewController
vc?.selectedObject = (myCounters?[indexPath.row])!
navigationController?.present(vc!, animated: true, completion: nil)
print("ewwewew")
}
Just pass the index path in the sender parameter, pretty easy:
func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
performSegue(withIdentifier: "ShowDetail", sender: indexPath)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "ShowDetail" {
let indexPath = sender as! IndexPath
let svc = segue.destination as! DetailViewController
svc.selectedObject = myCounters![indexPath.row]
}
}
Try this,

func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
print("Index : \(indexPath.row)")
var tempIndex: Int!
var tempIdentifier: String!
self.tempIndex = indexPath.row //You can store indexpath.row value in temp variable. And then then you can access it while performing any other functions.
self.tempIdentifier = "ShowDetail" //This upto your needs.
}
//UIStoryboardSegue to move over another controller accordingly.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
switch segue.identifier {
case "ShowDetail":
if let ip = myTableView.indexPathForSelectedRow{
if let svc = segue.destination as? DetailViewController{
svc.selectedObject = (myCounters?[tempIndex])!
}
}
default:
print("error in segue")
}
}
I'm trying to change the title of the new navigation bar to match the tableview cell that was pressed, moving the user to the next viewcontroller.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
folderCellSelected = folderNames[indexPath.row]
}
Grabs the name of the cell that was selected
override func viewDidLoad() {
super.viewDidLoad()
self.title = FoldersViewController.folderCellSelected
// Do any additional setup after loading the view.
mindmapNames.append("Task")
mindmapNames.append("Other Task")
}
And is supposed to insert the name of the cell, changing the title of the new page
But i can't figure out what to write instead of FoldersViewController.folderCellSelected
Instance member 'folderCellSelected' cannot be used on type 'FoldersViewController'
is the error i get
You can use the function override func prepare(for segue: UIStoryboardSegue, sender: Any?)
to send a value to the next view controller like that :
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var mytbl: UITableView!
var foldernames = ["test","test1"]
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "next"{
let nextViewController = segue.destination as! NextViewController
nextViewController.myTitle = foldernames[sender as! Int]
}
}
}
extension ViewController : UITableViewDelegate,UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return foldernames.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = foldernames[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "next", sender: indexPath.row)
}
}
myTitle is a variable from NextViewController
and then in the NextViewController do this :
class NextViewController: UIViewController {
var myTitle = ""
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.title = myTitle
}
I have some cell's (image bellow) created by tab[] I need to segue correct value to another view (moreViewController) on this view I have 'nazwa' 'szerokosc' 'dlugosc' and I need to save to nazwa correct "place" from cell etc
have somebody any solution? I search it but I don't find :/
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath){
self.performSegue(withIdentifier: "more", sender: tableView)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let destViewController:moreViewController = segue.destination as! moreViewController
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return nazwaTab.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! cellTableViewCell
let nazwa = nazwaTab[indexPath.row]
let szerokosc = szerokoscTab[indexPath.row]
let dlugosc = dlugoscTab[indexPath.row]
cell.nazwaLabel.text = nazwa
cell.szerokoscLabel.text = szerokosc
cell.dlugoscLabel.text = dlugosc
return (cell)
}
Declare a variable nazwa in MoreViewController and assign a value to it before segueing to it.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let identifier = segue.identifier ?? ""
switch identifier {
case "more":
guard let vc = segue.destination as? MoreViewController else {
return
}
vc.nazwa = self.clickedNazwa
default:
break
}
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath){
self.clickedNazwa = nazwaTab[indexPath.row]
self.performSegue(withIdentifier: "more", sender: tableView)
}
You can save a selected row to global variable and use it after call: prepare(for segue: UIStoryboardSegue, sender: Any?)