Swift 3 : Tableview select row goes to different navigation views - swift

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

Related

How to make 2ndVC tableview didSelectRowAt working only if i come from 1stVC btn tap in swift

I have two Viewcontrollers..
in 2ndVC i have tableview.. here i dont want didSelectRowAt method to work.. i need only this method to work when it navigates from 1stVC btnAction
in 1stVC textfield i need to fill with 2ndVC tableview's selected row text.. so i have placed button on textfield and in btnAction i gave navigation to 2ndVC.. now i need tableview selected row text in textfield
in 2ndVC i wrote didSelectRowAt here i dont want to select any row but in this viewcontroller if i select any row its going to 1stVC.. i want to select row only if i navigate from 1stVC btn
class 2ndVC: UIViewController {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let viewController = self.storyboard?.instantiateViewController(withIdentifier: "1stVC") as! 1stVC
viewController.empLoc = empDetail[indexPath.row]
self.navigationController?.pushViewController(viewController, animated: true)
}
}
1stVC code: if i go from here to 2ndVC then only i need to select tableview
class 1stVC: UIViewController {
#IBAction func empBtn(_ sender: Any) {
let viewController = self.storyboard?.instantiateViewController(withIdentifier: "2ndVC") as! 2ndVC
self.navigationController?.pushViewController(viewController, animated: true)
}
}
how to stop tableview row selecting method in 2ndVC.. and select tableview row if come from 1stVC..
please help me with code.
Have a variable in 2nd viewController say isfromFirstVC and set to false by default. When you are presenting 2nd VC from 1st set that variable to true (viewcontroller.isfromFirstVC = true) . In 2nd VC make use of this variable in didSelectRowAt method.

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

Navigate from a ViewController to an another on didSelectRowAt programmatically

I have a UIViewController that contains a custom UITableView. The table has a custom UITableViewCell too.
How to navigate from the first ViewController to an another when you select/click one of the rows?
Note
I have not used StoryBoard.
Update
This my code. Each one of the classes are external file. Let me know, if you need more code.
class TestViewController: UIViewController, UITableViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
view.addSubview(testTableView)
}
let testTableView: TestTableView = {
let table = TestTableView()
table.register(TestTableViewCell.self, forCellReuseIdentifier: TestTableViewCell.identifier)
return table
}()
}
class TestTableView: UITableView, UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: TestTableViewCell.identifier, for: indexPath)
return cell
}
}
class TestTableViewCell: UITableViewCell {
static let identifier = "testCell"
}
Here is a complete answer:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let newViewController = NewViewController()
self.navigationController?.pushViewController(newViewController, animated: true)
}
In UIKit in order to programmatically navigate from TableCell you can do it without storyboard.
You have two ways to view next viewController
If you want to present .......
animating from bottom to top
(one thing to remember) you can not present new view without dismissing previous presented screen, otherwise app crash due to conflict of presented screen
yourTableView.deselectRow(at: indexPath, animated: true)//used for single Tap
let vC = YourViewController (nibName: "" , bundle : nil)
vC.modalPresentationStyle = .fullScreen //this line is optional for fullscreen
self.present(vC, animated: true , completion: nil)
Or if you want to View your viewController normally (2 is batter) ....
animate from right to left
yourTableView.deselectRow(at: indexPath, animated: true)
let vC = YourViewController()
self.navigationController?.pushViewController(vC, animated: true)
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let vc = yourCustomVCName (nibName: "yourCustomVC nibName" , bundle : nil)
self.present(vc, animated: true , completion: nil)
}

Custom UITableViewCells repeating when navigating to viewcontroller

I am making a running app, and would like the user to see the races/marathons in their city. When clicking on the cell the user is navigated to a new view controller with details of the marathon. But upon pressing the back button to go back to the table the cells repeat. for example, if scrolling on the table it will display cell 1, cell 2,cell 3, cell 4,cell 1, cell 2,cell 3, cell 4 and will repeat more every time I navigate to the view controller with the table.
The code for the table is:
//MARK: TableView
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return exhibitions.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let singleCell: marathonTableViewCell = tableView.dequeueReusableCellWithIdentifier("marathonCell") as! marathonTableViewCell
singleCell.marathonName.text = exhibitions[indexPath.row]
singleCell.entryNumber.text = "\(entryNumber[indexPath.row])"
singleCell.entries.text = "\(entires[indexPath.row])"
return singleCell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("marathonDetail", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if(segue.identifier == "marathonCardDetail"){
var upcoming: marathonDetailViewController = segue.destinationViewController as! marathonDetailViewController
let indexPath = self.marathonsTableView.indexPathForSelectedRow!
let currentCell = marathonsTableView.cellForRowAtIndexPath(indexPath) as! marathonTableViewCell
let marathonEvents = currentCell.marathonName.text
upcoming.nameMarathon = marathonEvents
self.marathonsTableView.deselectRowAtIndexPath(indexPath, animated: true)
}
}
I am using swift, Xcode 7, and Parse as my backend.
I think u have to init ur array before update tableview.
When u click back button, tableview may refresh.
So make some code that makes ur array new, and then call tableview.reloadData()

How to call table view controller?

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