Swift - pass data from tableview to third viewcontroller - ios

I have too much code to paste it all in, so I'm going to be vague. I think I just need a general idea of what to do, and then I'll be able to do it.
I have a beautiful table built with a list of local businesses. When you click on one, it opens up the DetailView, with some great information about the business. I have a MAP button on the DetailView that triggers Thirdview with a Mapview inside of it.
I'm having issues retrieving data from the cells in the TableView in the Thirdview.
My views:
Tableview => DetailView => Thirdview
In my Thirdview, can I call the information from Tableview?
Or is it easier to pass the information from DetailView to Thirdview?
Thanks!

TableView
var objects: [MyObject] = []
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let myObject = objects[indexPath.row]
}
override func prepare(for segue: UIStoryboardSegue, sender: Any) {
if segue.identifier == "mySegue" {
let detailVC = segue.destination as! MyDetailVC
detailVC.dataFromTableView = myObject
}
}
Detail View
var dataFromTableView = MyObject()
override func prepare(for segue: UIStoryboardSegue, sender: Any) {
if segue.identifier == "mySegue" {
let thirdVC = segue.destination as! MyThirdViewController
thirdVC.dataFromDetailView = dataFromTableView
}
}
Third View
var dataFromDetailView = MyObject()
override func viewDidLoad() {
print(dataFromDetailView)
}

Related

Dismiss my view controller but "prepare" the view controller underneath

I have a modally-presented ViewController that has a UITableView inside it. When the user clicks "Days", it shows this view controller (modally). Here's my Storyboard:
What I want to do is, when I click one of the cells in the table view in the modal, I want to dismiss the modal, but also load new data in the root view controller.
How can I have access to the root view controller from a segued view controller?
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.dismiss(animated: true, completion: nil)
}
// MARK: - Navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let destinationVC = segue.destination as! DayView
if let indexPath = tableView.indexPathForSelectedRow {
destinationVC.day = days![indexPath.row]
}
}
I want something like what I've written above, but while my modal does get dismissed, but what I want is for somehow the code in the prepare function to fire when a TableViewCell is clicked.
A shorter and simpler method than protocol/delegate is to create a closure:
For sending a String back, In First ViewController:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let viewControllerB = segue.destination as? ViewControllerB {
viewControllerB.callback = { message in
//Do what you want in here!
}
}
}
In ViewControllerB:
var callback : ((String) -> Void)?
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
callback?("Your Data")
self.dismiss(animated: true, completion: nil)
}
you are in the right path,you need to add two more functions 1. unwindsegue and one this is not destination its source so you need change to source from destination.
// MARK: - Navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let destinationVC = segue.source as! DayView
if let indexPath = tableView.indexPathForSelectedRow {
destinationVC.day = days![indexPath.row]
}
}
for Reference : How to Pass Data in an Unwind Segue

Prepare for segue in TableViewDelegate methods

[SOLVED]
Let me explain my problem;
I have a bunch of Event object which appears in tableView cells.
And these objects store in events array
var events: [Event]
Also i have another view controller(DetailViewContoller), in that view controller i have a variable for receiving event object from tableview.
import UIKit
class EventDetailViewController: UIViewController {
var event: Event?
override func viewDidLoad() {
super.viewDidLoad()
print(event?.name)
}
When i tapped the cells i want to pass my current event object to variable(indicated on above) in DetailViewController. So i tried this ->
extension EventListViewcontroller:UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// Whenever cells tapped, related object needs to pass DetailViewController
performSegue(withIdentifier: K.Segues.eventListToDetail, sender: self)
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == K.Segues.eventListToDetail {
let VC = segue.destination as! EventDetailViewController
VC.event = events[indexPath.row]
}
}
}
But unfortunately after segue performed when i checked the event variable in DetailViewController it was shown as a nil. So question is, how can i pass my tapped event cell to other view controller?
Note: i've found this topic How do you test UIStoryBoard segue is triggered by didSelectRow(at:) but it didn't help my problem...
In your class
class ViewController: EventListViewcontroller {
var selectedIndex: IndexPath? = nil
}
And change your code in didSelect as
extension ViewController:UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// Whenever cells tapped, related object needs to pass DetailViewController
self.selectedIndex = indexPath
performSegue(withIdentifier: K.Segues.eventListToDetail, sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let indexPath = self. selectedIndex, segue.identifier == K.Segues.eventListToDetail {
let VC = segue.destination as! EventDetailViewController
VC.event = events[indexPath.row]
}
}
}
Hope this helps

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

Passing data between segue with Swift 2.0

I seem to be following tutorials to the tee yet I can't get my data to pass to my second view controller without being nil.
I am new to Swift so I'm probably also not using optionals correctly. Here is how I have my code set up.
import UIKit
class DetailsViewController: UIViewController {
var book : PLBook?
override func viewDidLoad() {
super.viewDidLoad()
//View Did Load
print(self.book)
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
}
}
Then this is how I am presenting the second view controller and preparing for segue.
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("toDetailVC", sender:self)
}
//MARK: Navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "toDetailVC"){
//prepare for segue to the details view controller
if let detailsVC = sender?.destinationViewController as? DetailsViewController {
let indexPath = self.tableView.indexPathForSelectedRow
detailsVC.book = self.books[indexPath!.row]
}
}
}
In the second view controller, the book var is always nil. Any ideas how I can get the data to pass?
Try This:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "toDetailVC") {
//prepare for segue to the details view controller
let detailsVC = segue.destinationViewController as! DetailsViewController
let indexPath = self.tableView.indexPathForSelectedRow
detailsVC.book = self.books[indexPath!.row]
}
You should be using segue.destinationViewController, not sender?.destinationViewController.

How to call (show) another View Controller when clicked on the cell of Table View in Swift

I'm new in Swift. I want to learn that, how to call another View Controller when the user clicks on cell of Table View.
Thanks in advance.
write following code :
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("showItemDetail", sender: tableView)}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if segue.identifier == "showItemDetail" {
let indexPath:NSIndexPath = self.tableView.indexPathForSelectedRow()!
let detailVC:ItemDetailViewController = segue.destinationViewController as ItemDetailViewController
detailVC.item = items[indexPath.row] as Item
}
}
add a viewController from storyboard and add a segue from tableview cell to viewController with identifier "showItemDetail";
will navigate too detailViewController
In First View Controller
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!)
{
if segue.identifier == "showItemDetail"
{
let indexPath:NSIndexPath = self.tableView.indexPathForSelectedRow()!
let destination = segue.destinationViewController as DetailViewController
destination.name = "llkin Elimov"
}
In second Detail View Controller
public DetailViewController
{
var name = "name" as String //After you created the segue in main.storyboard, in name , you will get your parsed string automatically
}
Hope my code is clear for you :)

Resources