Swift: show name in ViewController - ios

I have array with names in TableViewController and I have ViewController. If I click on cell in TableViewController I want to show name from array in ViewController navigation bar title. How to do it?

Try this:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
navigationItem.title = myArray[indexPath.row]
}
UPDATE:
If you are using storyboards, you can:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
let ame = myArray[indexPath.row]
performSegue(withIdentifier: "ViewController", sender: selectedName)
}
then, recover the selectedName in prepareForSegue and set the title for destinationVC there:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let selectedName = sender as? String,
let viewController = segue.destination as? ViewController {
detailViewController.navigationItem.title = selectedName
}
}

you can set title of viewcontroller by
suppose you have a view Controller
class UIViewController{
// make a variable in your view controller like
var titleName:String?
override func viewDidLoad(){
self.tittle = self.titleName
}
}
from your tableViewController you can pass the name to your ViewController
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let controller = self.storyboard.instantiateViewController(withIdentifier: "pass you view controller storyboard id here") as! ViewController
controller.titleName = yourArray[indexPath.row]
self.navigationController.pushViewController(controller , animated: true)
}

If you are using Storyboard, and want to navigate and pass "title" to the SecondViewController:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let name = YOUR_ARRAY[indexPath.row]
let storyboard = UIStoryboard(name: "Main", bundle: nil)
guard let destinationVC = storyboard.instantiateViewController(withIdentifier: "YOUR_SECOND_VIEW_IDENTIFIER") as? SecondViewController else { return}
destinationVC.title = name
navigationController?.pushViewController(destinationVC, animated: true)
}
If you use Interface Builder
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let name = YOUR_ARRAY[indexPath.row]
let destinationVC = SecondViewController(nibName: "YOUR_SECOND_VIEW_NAME", bundle: nil)
destinationVC.title = name
navigationController?.pushViewController(destinationVC, animated: true)
}

Related

How to pass tableView label to name variable in another viewController?

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).

When transferring text from a cell to a label in the next VC, it doesn't appear the first time the VC is opened

I am making an app where you create memories into a tableView and you tap on a cell and it takes you to its designated VC, I am trying to make it so that when the cell is tapped, the text from inside that table cell is taken into the label in the next VC. This works but the problem is that when the view is first opened, the text doesn't appear inside the label, even though the console says that the text has loaded correctly:
TableView with a test cell in it.
First time the VC for the cell is opened
Console saying that the text has transferred and loaded correctly
Second time the VC is opened.
Here is my transferring and loading code for the ViewControllers:
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate {
var selectedRow : Int = 0 + 1
var selectedNameVC : String?
var favourites: [NSManagedObject] = []
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
//MARK:- New CoreData methods
let favMemory = favourites[indexPath.row]
cell.textLabel?.text = favMemory.value(forKeyPath: "name") as? String
if #available(iOS 13.0, *) {
cell.backgroundColor = UIColor.secondarySystemGroupedBackground
} else {
// Fallback on earlier versions
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
selectedRow = indexPath.row
let cell = tableView.cellForRow(at: indexPath)
let favMemory = cell?.textLabel?.text
selectedNameVC = favMemory
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destination = segue.destination as? FavouritesViewController {
destination.row = selectedRow
destination.selectedName = selectedNameVC
}
}
class FavouritesViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate, UITextFieldDelegate, UITextViewDelegate {
var selectedName: String?
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(true)
labelText.text = selectedName
if labelText.text == "" as String? {
print("Title has not loaded correctly.")
} else {
print("Title has loaded correctly.")
}
}
First, you shouldn't get values from cells... get them from your data source (which is what you used to set the values).
So, in didSelectRowAt instead of:
let cell = tableView.cellForRow(at: indexPath)
let favMemory = cell?.textLabel?.text
you should do:
let favMemory = favourites[indexPath.row]
However, that's not what's causing your issue.
I'm assuming in your Storyboard you have a "Show Segue" connected from your prototype cell to your FavouritesViewController. If that's the case, prepare(for segue: ...) is called before didSelectRowAt. To confirm this, change your code to:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
selectedRow = indexPath.row
// don't do this
//let cell = tableView.cellForRow(at: indexPath)
//let favMemory = cell?.textLabel?.text
let favMemory = favourites[indexPath.row]
print("In didSelectRowAt --- Setting var selectedNameVC = favMemory: \(favMemory)")
selectedNameVC = favMemory
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destination = segue.destination as? FavouritesViewController {
print("In prepareForSegue --- Setting selectedName in FavouritesViewController = selectedNameVC: \(selectedNameVC)")
destination.row = selectedRow
destination.selectedName = selectedNameVC
}
}
This is what you should see in the debug console:
In prepareForSegue --- Setting selectedName in FavouritesViewController = selectedNameVC: nil
In didSelectRowAt --- Setting var selectedNameVC = favMemory: Test
Title has loaded correctly.
As you see, prepareForSegue runs first, so the value of selectedNameVC is nil (it hasn't been set yet).
To fix this, you could set your variables in willSelectRowAt instead of in didSelectRowAt:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
}
func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
selectedRow = indexPath.row
let favMemory = favourites[indexPath.row]
selectedNameVC = favMemory
return indexPath
}
Alternatively, create your Segue in Storyboard, but do not connect it to the cell. Instead, give it an Identifier (such as "ShowFavourites"), and in didSelectRowAt, set your vars and call performSegue:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
selectedRow = indexPath.row
let favMemory = favourites[indexPath.row]
selectedNameVC = favMemory
performSegue(withIdentifier: "ShowFavourites", sender: nil)
}

how to get data when cell accessory is tapped in ios

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")
}
}

Go to the ViewController by clicking on the TableView cell in swift

there is a class MenuViewController in which the array recorded in the table is recorded:
import Foundation
import UIKit
class MenuViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var menuTableView: UITableView!
let myTitle = ["Помощь", "Информация", "Поддержка"]
override func viewDidLoad() {
super.viewDidLoad()
menuTableView.delegate = self
menuTableView.dataSource = self
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return myTitle.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = menuTableView.dequeueReusableCell(withIdentifier: "MenuCell") as! MenuTableViewCell
cell.labelText.text = myTitle[indexPath.row]
return cell
}
}
What do you need to write in it to go to Info Controller?
I assume you are using storyboards. First you need to set up some sort of connection between your two viewcontrollers. You can do this by setting up a "segue". You hold ctrl+click drag from the first viewcontroller to the 2nd viewcontroller. It looks like this:
When you let go of the mouse, you will see this:
Click on Show. Now you will have created a segue.
Now you need to name it. So click on the segue that shows up in the storyboard. It is basically just an arrow from the Menu View Controller to the Info View Controller. On the right hand side you will see a place where you can name it (give it an identifier):
Now ... you have done all you needed to do in the storyboard. Now in your actual code in the MenuViewController, you need to associate clicking the tableviewcell. You do this by using the delegate method didSelectRowAt.
I see you have already set up the delegate with this line:
menuTableView.delegate = self
That ensures that didSelectRowAt will be called whenever the user taps on a row.
So now what you want to do is write the code to perform the segue:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.performSegue(withIdentifier: "YourSegueName", sender: self)
}
Note:
Here is more information on interacting with a tableview row:
How to detect tableView cell touched or clicked in swift
Here is more information about segues:
IOS - How to segue programmatically using swift
There are many more customizations you can do ... such as passing data through to the next viewcontroller via the segues. Here's how:
Pass data through segue
implement UITableViewDelegate method:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
//To InfoViewController I am considering you have created InfoViewController with XIB
let controller = InfoViewController(nibName: "YourNibName", bundle: nil)
//Present Your Controller
self.present(controller, animated: true) {
}
//Push Your controller if your view is already part of NavigationController stack
self.navigationController?.pushViewController(controller, animated: true)
}
Just add a
nextViewController.didMove(toParentViewController: self) inside a
"didSelectRowAt". Example given below.
This is for List a tableview cell:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellIdentifier = "cell"
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! PatientFamilyDetailTableViewCell
cell.txt_patientName.text = patientname[indexPath.row]
// Configure the cell...
return cell
}
Now it's for Select a Table view cell:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) {
if cell.isSelected {
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let nextViewController = storyBoard.instantiateViewController(withIdentifier: "medtestmain") as! medTest
patient_id = relation[indexPath.row]
patient_name = patientname[indexPath.row]
UserDefaults.standard.set(patient_id, forKey: "patient_id")
UserDefaults.standard.set(patient_name, forKey: "patient_name")
self.addChildViewController(nextViewController)
nextViewController.view.frame = self.view.frame
self.view.addSubview(nextViewController.view)
nextViewController.didMove(toParentViewController: self)
}
}
}

Pass mapkit data between two view controllers

I have two view controllers. One of them is a search view controller which uses mapkit to allow the user to search for a location.
I want to be able to click on a specific cell, and then assign the subtitle of the cell to a textfield in another viewcontroller. Does anyone have ANY idea on how to do this?!
You can implement below method of UITableViewDelegate.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: false)
let cell = tableView.cellForRow(at: indexPath) as! MyCell
let vc = MyViewController()
vc.subtitle = cell.subTitle.text
present(vc, animated: true, completion: nil)
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: false)
DispatchQueue.main.async {
self.performSegue(withIdentifier: "tosecondVC", sender: indexpath.row)
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let index = segue.destination as! secondViewController
index.indexinSecondVC = sender as! Int
}

Resources