How to make a push segue when a specific UITableViewCell is selected - swift

I am working on my first iOS app and new student to swift.
Everything is working however I am having trouble figuring out how to segue from a specific cell to a third view controller. I have a IOS UITableView with three sections and a total of (44) cells. All cells when tapped segue to one DetailVC titled: showProductDetai which is fine. The problem that I am having is that I need to have only (1) particular cell in section 0 row 5 in the UITableView to go to its own ViewController in which I titled: second view controller instead of the normal showProductDetail VC. Is there an intelligent way to make the specific cell in section 0 row 5 of the tableView go to second view controller when selected?
Here is my current code that is working. How would I code to make the changes?
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ProductCell", for: indexPath) as! ProductTableViewCell
// Configure the cell...
let productLine = productLines[indexPath.section]
let products = productLine.products
let product = products[indexPath.row]
cell.product = product
return cell
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
let productLine = productLines[section]
return productLine.name
}
// Mark: UITableViewDelegate
var selectedProduct: Product?
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
let productLine = productLines[indexPath.section]
let product = productLine.products[indexPath.row]
selectedProduct = product
performSegue(withIdentifier: "ShowProductDetail", sender: nil)
}
// Mark: - Navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
if segue.identifier == "ShowProductDetail" {
let DetailVC = segue.destination as! DetailViewController
DetailVC.product = selectedProduct
}
}

see what I did here? You can use the indexPath parameter to get the section & row the user touched, and then you can set up your programmatic segue.
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
if ((indexPath.section == 0) && (indexPath.row == 5)) {
performSegue(withIdentifier: "GoToSecondViewController", sender: nil)
} else {
let productLine = productLines[indexPath.section]
let product = productLine.products[indexPath.row]
selectedProduct = product
performSegue(withIdentifier: "ShowProductDetail", sender: nil)
}
}

Write a segue code for the desired section and row:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.section == 0 && indexPath.row == 5 {
//Perform Segue
} else {
//Rest of the functionality
}
}
Make sure you have connected proper Sugues and given proper identifiers in Storyboard.
You don't need to write prepare Segue method

Related

Swift - How to access cells name

import UIKit
class TableViewControllerOne: UITableViewController {
let musicArray = ["Old Town Road", "Starboy"]
var songName = ""
override func viewDidLoad() {
super.viewDidLoad()
}
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return musicArray.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath)
cell.textLabel!.text = musicArray[indexPath.row]
//here is the problem
songName = cell.textLabel!.text!
return cell
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
var vc = segue.destination as! ViewControllerOne
vc.songFinalName = self.songName
}
}
So I am doing music player App, but I don't know how to play current song. I have all songs in a row(identifier is MyCell). When I click on the cell named for example ,,Starboy" it should get that name and pass the data to the other VC and there play it, but always it only plays the latest thing that is in the raw, so for example there are 3 songs: Old Town Road, Starboy, Hello and it can play only the latest so in this example it is Hello. Can someone help me please? Thank you for reading.
You need to implement tableview's delegate method didSelectRowAt which will update the songName property whenever a user taps on any row of table view
public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
songName = musicArray[indexPath.row]
}
Moreover, remove songName = cell.textLabel!.text! from cellForRowAt: indexPath method

Use segue for item selected in table view

I've looked at other possible solutions here on StackOverflow but don't quite think they apply to my issue or simple I don't understand is the greater possibility. Here is what I am trying to do. I have a tableview with sections and items in each section. I want to segue to a different view controller based on the selection made by the user in the tableview. I have set up a sample with the following code with segues "report1Segue" and "report2Segue" as an example.
class ViewController: UIViewController {
#IBOutlet weak var reportTableView: UITableView!
let reportGroup = ["Dietary", "Weight", "Sleep", "Meditation", "Fitness"]
let report = [["Calorie Breakdown", "Net Calories"], ["Last 3 Months"], ["Last 3 Months"],["Last 3 Months"],["Exercises by Type"]]
func numberOfSections(in tableView: UITableView) -> Int {
return report.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return reportGroup[section]
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "reportSegue" {
if let reportVC = segue.destination as? Report1ViewController, let indexPath = reportTableView.indexPathForSelectedRow {
reportVC.dataToDisplay = report[indexPath.section][indexPath.row]
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}
extension ViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return report[section].count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = report[indexPath.section][indexPath.row]
return cell
}
}
extension ViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "report1Segue", sender: nil)
}
}
Any guidance is always greatly appreciated.
Swift 5.2
For fixed data in a UITableView you can do it like this:
// Hard code your IndexPath references
// This will make the code easier to read in the delegate methods
enum TableIndex {
static let calorieBreakdown = IndexPath(row: 0, section: 0)
static let netCalories = IndexPath(row: 1, section: 0)
static let weightLastThreeMonths = IndexPath(row: 0, section: 1)
static let sleepLastThreeMonths = IndexPath(row: 0, section: 2)
static let meditationLastThreeMonths = IndexPath(row: 0, section: 3)
static let fitnessExercises = IndexPath(row: 0, section: 4)
}
// Example - perform whatever Segues you actually need
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
switch indexPath {
case TableIndex.calorieBreakdown:
performSegue(withIdentifier: "report1Segue", sender: self)
case TableIndex.weightLastThreeMonths, TableIndex.sleepLastThreeMonths:
performSegue(withIdentifier: "report2Segue", sender: self)
default:
break
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let indexPath = tableView.indexPathForSelectedRow else { return }
let data = report[indexPath.section][indexPath.row]
switch segue.identifier {
case "report1Segue":
if let dest = segue.destination as? Report1ViewControler {
dest.dataToDisplay = data
}
case "report2Segue":
if let dest = segue.destination as? Report2ViewControler {
dest.dataToDisplay = data
}
default:
break
}
}
It seems like what needs to happen here is 1, in your didSelectRowAt, you need to figure out what is tapped, So based on how you are displaying the cells, you need to do the same here to find out what cell is tapped. Then based on that selection you will either have a switch case or if else statements that will each call its unique performSegue so that based on a cell selection it will go to a different selection.
For your example, you 'selection' is report[indexPath.section][indexPath.row]
then if switch or if else
if will be like
if selection == "Last 3 Months" || selection == "Net Calories" {
performSegue(withIdentifier: "report1Segue", sender: nil)
} else if selection == "Calorie Breakdown" {
performSegue(withIdentifier: "report2Segue", sender: nil)
}
Hope this helps you out.

cast UIButton from cell to run a query and send results to another cell

i'm querying data from a VC and sending the output to another VC that has a TableViewCell. with the results in the cell, i'm trying to run another query to Firebase and display the results in another VC that has a custom prototype cell. i'm able to manually run the queries in both instances, my issue(confusion) is how to call the IBAction button to run the query. I dont know how to cast the cell to run the query and performSegue to the thirdVC
mainVC
#IBAction func getDataPressed(_ sender: Any) {
query......
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "cell1" {
let vc = segue.destination as! secondVC
vc.data = data
self.performSegue(withIdentifier: "cell1", sender: self)
}
}
secondVC
func tableView(_ tableView: UITableView, numberOfRowsInSection section:
Int) -> Int {
return info.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath:
IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier:
"secondVcCell", for: indexPath)
as? secondVcCell {
cell.configureCell(inf: info[indexPath.row])
return cell
}
return UITableViewCell()
CustomCellDelegate
protocol CustomCellDelegate {
func callSegueFromcell(_ sender: Any?)
secondVcCell
var delegate: CustomeCellDelegate?
#IBOutlet weak var cellBtn: UIButton
#IBAction func getDataPressed2(_ sender: Any) {
query ........
}
if(self.delegate !=nil)
self.delegate.callSegueFromcell(Any)
thirdVC
func tableView(_ tableView: UITableView, numberOfRowsInSection section:
Int) -> Int {
return info2.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath:
IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: "thirdVcCell",
for: indexPath)
as? ThirdVcCell {
cell.configureCell(inf1: info2[indexPath.row])
return cell
}
return UITableViewCell()
for the query, just call the function for querying in the IBAction button by typing the function within the range.
for the second cast if you are pulling from firebase then you will need to change your code to include firebase DataBase or Firestore, if you are taking it manually then you need to do the same as the first cast but make sure the indexPath is correct

UITableView - Execute a different function in primary view controller, based on row number of UITableView

Using the following code to create my UITableView which works well:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return(arrayOfImages.count)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! ViewController2TableViewCell
cell.niceImage.image = UIImage(named: arrayOfImages[indexPath.row] + ".png")
return(cell)
}
Then, I am using the following code to unwind segue onto ViewController1 and execute my function, which also works well:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let destVC = segue.destination as! ViewController
destVC.posn += 1
destVC.myFunction(Parameter1: 1)
arrayOfImages contains 10 images (for now). I want each image (aka each row in my UITableView) to execute a different function in destVC. I.e the function is dependant on row number. Using the above code, the same function is executed on every row, which is not ideal
I tried utilising the following:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
myIndex = indexPath.row
}
And then making my function dependant on indexPath.row's value, but myIndex always came up as 0, regardless of what row it actually was
You send integer 1 for your destVC function's parameter everytime. Thats the problem. Send the selected indexPath.row of tableView in prepareForSegue method
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let indexPath = tableView.indexPathForSelectedRow {
let destVC = segue.destination as! ViewController
destVC.posn += 1
destVC.myFunction(Parameter1: indexPath.row)
}
}

SWIFT if statement and segue

I have a problem with if statement and segue
can I make a connection between them !
I have an array of these states ["Florida","NY"]()
my idea, for example, if I clicked "Florida"<(this is "string") on table view
I want the segue moves me from this table view to another table view
and if I clicked "NewYork" on tableView I want the segue moves me from this table view to another that has information about NY
thanks
You could do something like this:
class SelectCityViewController : UITableViewController {
// store a reference to use in transition
var selectedCity : String?
let cities : [String] = ["New York", "San Francisco", "Los Angeles"]
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = //TODO: your implementation here
cell.textLabel?.text = cities[indexPath.row]
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.selectedCity = cities[indexPath.row]
performSegueWithIdentifier("YOUR_SEGUE_IDENTIFIER", nil)
}
override func tableView(tableView: UITableView, numberOfItemsInSection section: Int) -> Int {
return self.cities.count
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let vc = segue.destinationViewController as? CityDetailViewController {
vc.selectedCity = self.selectedCity!
}
}
}
Then your second view controller would have a variable with your selected city stored in it so you could setup your content accordingly
class SelectedCityDetailViewController : UITableViewController {
// Set during the segue
var selectedCity : String!
// The rest of your methods
}
you can do something like this in didSelectRowAtIndexPath.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let currentCell = tableView.cellForRowAtIndexPath(indexPath)! as UITableViewCell
if let text = currentCell.textLabel?.text {
if text == "Florida"{
// segue tableview controller
} else if text == "NY" {
//another segue
}
}
}
Take a viewController and add a tableView. Add two another view controllers, one for the NY info and the other containing one more uiTableView. Create two segues from main controller to the other two. Name the segues so that you can refer to them in the code. In didSelectRowAtIndexPath add the following Code:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let currentCell = tableView.cellForRowAtIndexPath(indexPath)! as UITableViewCell
if indexPath.row == 0{
self.performSegueWithIdentifier("florida", sender: nil)
}else if indexPath.row == 1{
self.performSegueWithIdentifier("ny", sender: nil)
}
}
Please check this Link. I have created a demo project for you. I think you are a starter to the iOS development. Carry On!! :)