How to call table view controller? - swift

I need to call a second "table view controller" when a custom cell in the first "table view controller" is tapped:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if indexPath.row == 0 {
var controller: TableViewController1 = storyboard?.instantiateViewControllerWithIdentifier("demo1") as! TableViewController1
self.navigationController?.pushViewController(controller, animated: true)
} else {
var controller: TableViewController2 = storyboard?.instantiateViewControllerWithIdentifier("demo2") as! TableViewController2
self.navigationController?.pushViewController(controller, animated: true)
}
}
This code is to call a custom "view controller" not a custom "table view controller".
Or do I need to call the "navigation controller" of the "table view controller"?

First, you need to make sure you select your main UITableViewController and embed a navigation controller by going to: Editor>Embedded In Navigation Controller. Then Ctrl+Drag from your first UITableViewController to the other two, selecting Manual Segue>Show. Make sure you name your segues in your storyboard, for example I use "table1" and "table2." Then you can use the following code:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if indexPath.row == 0 {
self.performSegueWithIdentifier("table1", sender: self)
} else {
self.performSegueWithIdentifier("table1", sender: self)
}
}

Related

storyboard elements not visible in view controller after segue

I added a view controller (vc2) with some simple form elements to it to my storyboard and made a segue ctrl-dragging from an existing tableviewcontroller (vc1) which is triggered by a trailing swipe button
I can see output from the print function (in the vc2 code below )in the debugger but my form elements aren't visible. And for some reason I had to manually set the background color, which had defaulted to black, not what was set on storyboard. I think this is related to the way I am loading vc2, but my attempts to change the code to a normal performSegueWithIdentifier caused a
'NSInvalidArgumentException', reason: 'Receiver () has no segue with
identifier
Then I deleted and remade the segue with no effect. So I changed the code back to this, which works but doesn't render the storyboard elements.
func clickView(forRowAtIndexPath indexPath: IndexPath) {
let myContents = UnitComponents[indexPath.row]
print("Clicked Report \(self.ProjectID) \(self.ShipListID) \(self.UnitName) \(myContents.sku)")
self.Sku = myContents.sku
let vc = ComponentViewController()
vc.Sku = myContents.sku
navigationController?.pushViewController(vc, animated: true)
}
Here is the vc2 code
import UIKit
class ComponentViewController: UIViewController {
var Sku = ""
var UnitName = ""
var ShipListID = ""
var ProjectID = ""
#IBOutlet var damageDesc: UITextView!
#IBOutlet var repairCost: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
print("Hello World \(Sku) \(UnitName) \(ShipListID) \(ProjectID)");
// Do any additional setup after loading the view.
}
#IBAction func saveReport(_ sender: Any) {
print("damageDesc \(String(describing: damageDesc ?? nil))")
print("repairCost \(String(describing: repairCost ?? nil))")
}
}
How can I fix my code so the storyboard layout etc gets loaded and I can see the form elements in the app?
Is this the wrong way to go to another view controller? I ask because it seems like some SO questions around this topic suggest it isn't calling the storyboard correctly. I'm searching for a swift 5 example of how to do this and only find references to instantiateViewControllerWithIdentifier("ViewController") which doesn't seem to be in swift 5
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let vc = ShippingUnitsTableViewController()
vc.ShipListID = ShipLists[indexPath.row].ListID
vc.ProjectID = ProjectID
navigationController?.pushViewController(vc, animated: true)
}
you need to specify the storyboard in which the viewcontroller is located, and then instantiate the viewcontroller from that storyboard. Replace your func with the below one:-
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "ShippingUnitsTableViewController") as! ShippingUnitsTableViewController
vc.ShipListID = ShipLists[indexPath.row].ListID
vc.ProjectID = ProjectID
navigationController?.pushViewController(vc, animated: true)
}
and make sure (inside the Main.storyboard file) you give ViewController's (which needs to be presented) Storyboard ID to be ShippingUnitsTableViewController in the attributes inspector (see the image below):-
can you try
func clickView(forRowAtIndexPath indexPath: IndexPath)
instead, didSelectRow of tableview delegate methods or view controller's performSegueWithIdentifier ?
Ok the solution to this problem required changing how I moved between view controllers. The didSelectRowAt indexPath method below does not utilize the storyboard, which causes the destination view controller to be sort of an orphan and unaware of the storyboard segues.
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let vc = ShippingUnitsTableViewController()
vc.ShipListID = ShipLists[indexPath.row].ListID
vc.ProjectID = ProjectID
navigationController?.pushViewController(vc, animated: true)
}
I changed didSelectRowAt indexPath to this, and added the bits of necessary info to the prepareSegue method as shown below.
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.ListID = ShipLists[indexPath.row].ListID
performSegue(withIdentifier: "UnitsVC", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "UnitsVC"{
let nextViewController = segue.destination as? ShippingUnitsTableViewController
nextViewController!.ProjectID = self.ProjectID
nextViewController!.ShipListID = self.ListID
}
}

Delegate method to segue in tableviewcell

I have a delegate method where if I press a button in the tableview, it should segue to another view controller and pass along data but it doesn't seem to work.
func goToVC(uid: String) { //delegate method
performSegue(withIdentifier: "showVC", sender: self) //Do I need this
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "showVC", sender: self)
self.tableView.deselectRow(at: indexPath, animated: true)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showVC" {
if let indexPath = tableView.indexPathForSelectedRow {
let guestVC = segue.destination as! GuestViewController
guestVC.ref = userArray[indexPath.row].ref
}
}
class MainViewController: UIViewController {
// set the cell's delegate in the data source
// pass the object to the cell from the data source
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
cell.mainViewControllerDelegate = self
cell.object = someArray[indexPath.row]
}
// this is the method that gets called by the cell through the delegate
func pushToViewController(object: YourDataObject) {
let destination = SomeViewController()
destination.object = object
navigationController?.pushViewController(destination, animated: true)
}
}
class TheTableViewCell: UITableViewCell {
// create a delegate and a data object
var mainViewControllerDelegate: MainViewController?
var object: YourDataObject?
// this is the method that gets called when the button in the cell is tapped
#objc func buttonAction() {
mainViewControllerDelegate?.pushToViewController(object: object)
}
}
I highly recommend that beginners do not use Interface Builder. The less you use it early, the quicker you will understand more. Interface Builder is fool's gold for beginners.
You dont need delegate method here. Delegate method can be used if you need to pass the value from the child view controller.
What you are doing is exactly right. Make sure you set the segue identifier in the story board correctly.
And one more thing dont set your table IBOutlet as default tableView try setting a name apt for that table like toDoTable, so it will easy to debug.

Swift 3 : Tableview select row goes to different navigation views

Trying to create a simple app with Swift 3, using Xcode 8.2. Would like to have a hierarchy as follows:
Tab-bar View
-->TableView
----->TableView
--------->View
--------->TableView
--------->etc.
----->TableView
----->View
-->TableView
For example, main tab bar should have a tableView controller embedded inside a navigation controller. Clicking on a certain cell (index.path) should lead to a separate tableview or viewcontroller that itself can branch off into its own series of 'child' tables. The tables should be dynamic, and all have navigation control that leads back 'pop' to the most previous table/view controller.
Currently, for the main tableview, I have:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.row == List_Database_Indexes.employees {
let myWebView = self.storyboard!.instantiateViewController(withIdentifier: "Employees") as! UITableViewController
//self.present(myWebView, animated: true, completion: nil)
self.performSegue(withIdentifier: "Employees", sender: nil)
}
This works to bring up the Employees UITableViewController but does not have the navigationbar controller at the top. For example, from apple, if you click on in the image below 'General' row, you are lead to a navigation tableview that takes you to Passlock code, which takes you to Auto-lock, all with navigation.
Change your code to:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.row == List_Database_Indexes.employees {
let myWebView = self.storyboard!.instantiateViewController(withIdentifier: "Employees") as! UITableViewController
//self.present(myWebView, animated: true, completion: nil)
//self.performSegue(withIdentifier: "Employees", sender: nil)
self.navigationController?.pushViewController(myWebView, animated: true)
}
}
This method is delegate method. so it will apply on all of the cell for table because we have bind delegate to tableview. cell is subview of table view.
you have to give condition for wether the cell is selected or not..
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.row == //index of that cell {
let Employee = self.storyboard!.instantiateViewController(withIdentifier: "Employees") as! UITableViewController
self.navigationController?.pushViewController(Employee, animated: true)
}
}

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!! :)

Swift leave a row selected after changing viewcontroller

i have a two view application. If i select a row a segue load the second view Controller. I want that when i return back to my first controller the row is is still selected. I have tried with this:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.cellForRowAtIndexPath(indexPath)!
self.tableView.selectRowAtIndexPath(indexPath, animated: true, scrollPosition: UITableViewScrollPosition.None)
}
override func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
self.tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
but when returning back the row not remain selected. What's is the problem??
P.S.: I want no multiple selection, only one row at time.
If you are using a UITableViewController subclass as your source view controller, what I presume because you are overriding the table view delegate methods, you can use the flag clearsSelectionOnViewWillAppear on your view controller to get this behavior.
override func viewDidLoad() {
self.clearsSelectionOnViewWillAppear = false
}
Or you can set this in your Storyboard as well, when selecting the attributes selector of your source table view controller, you have to untick the Clear on Appearance checkbox.