Programmatically switching views using UITableView in Swift - ios

I can't switch to another view controller using UITableView. My code is like below.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let dashViewController = storyBoard.instantiateViewControllerWithIdentifier("menuView") as DashViewController
self.presentViewController(dashViewController, animated:true, completion:nil)
}
I click one of my cells, and it just does nothing.

I already found the answer, I forgot to put UITableViewDelegate.
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate{
}
And assign tableview with view controller

Related

Link a cell to call a different ViewController

I am new to Swift (I use 2.0) and haven't any programmed experience. So, I'm new ) trying to do something fairly simple. Link a UITableViewCell click to call a different ViewController. It's like user click on cell Cars and open new ViewController.
I have created ViewControllers (storyboard A,B,C,D,E).
How I can connect? If I correctly understood I should use didSelectRowAtIndexPath.
Code which I have done:
import UIKit
class FirstViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
let list = ["Cars", "Fruits", "Foods", "Toys"]
let listdesc = ["Toyota", "Apple", "Meat", "Fallout 4"]
let identities = ["A", "B", "C", "D"]
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return list.count;
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellIdentifier: String = "cell"
let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: cellIdentifier)
cell.textLabel?.text = list[indexPath.row]
cell.detailTextLabel?.text = listdesc[indexPath.row]
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
}
You should have to do in this way in didSelectRowForIndexPath:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let StoryBoard = UIStoryboard(name: "Main", bundle: nil)
if(list[indexPath.row] == "Cars") {
var vcA = STORYBOARD.instantiateViewControllerWithIdentifier("A") as! A
self.navigationController?.pushViewController(vcA, animated: true)
} else if(list[indexPath.row] == "Fruits") {
var vcB = STORYBOARD.instantiateViewControllerWithIdentifier("B") as! B
self.navigationController?.pushViewController(vcB, animated: true)
}
}
and other condition you will manage as I show....
As answered by Gaurav, you can check in didSelectRowAtIndexPath that which indexPath is selected and then navigate to that respective controller.
But if you are using different storyboards then self.storyboard instead of STORYBOARD may come in handy.
Also change the objects of your viewController from var to let as you are not changing them so they should be constants.
And the last one "Always avoid force unwrapping", handle the error yourself instead.
Try this.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
// If storyboard name is A.storyboard.
let storyboard = UIStoryboard(name: "A", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("nextViewControllerId") as! nextViewController // The `nextViewController` storyboardId is supposed as "nextViewControllerId"
self.presentViewController(vc, animated: true)
}
This will present nextViewController every time you click any cell. If you want specific cell to open different viewcontroller use you logic using conditions within this function.
1. Create a segue from TableViewController Scene to other
ViewControllerScene.
2. Give unique identifier to each scene.
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
//Based on your condition.
//Initiates the segue with the specified identifier from the current view controller's storyboard file.
performSegue(withIdentifier: "segueA", sender: self)
}
If you have three storyboard like Main, PreLogin and PostLogin. Then you declare first all storyboard like this:-
let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
let preLoginStoryboard = UIStoryboard(name: "PreLogin", bundle: nil)
let postLoginStoryboard = UIStoryboard(name: "PostLogin", bundle: nil)
You call different viewController from the didSelectRowAtIndexPath method like that:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
switch indexPath.row{
case 0:
let firstViewControllerScene = mainStoryboard.instantiateViewControllerWithIdentifier("firstViewControllerId") as! FirstViewController
self.presentViewController(firstViewControllerScene, animated: true)
case 1:
let secondViewControllerScene = preLoginStoryboard.instantiateViewControllerWithIdentifier("secondViewControllerId") as! SecondViewController
self.presentViewController(secondViewControllerScene, animated: true)
case 2:
let thirdViewControllerScene = postLoginStoryboard.instantiateViewControllerWithIdentifier("thirdViewControllerId") as! ThirdViewController
self.presentViewController(thirdViewControllerScene, animated: true)
default:
break
}
}
You have to prepare data something like this and
options = [
{
"category":"Cars"
"subcat":"Cars"
"viewType":"A"
},
{
"category":"Fruits"
"subcat":"Apple"
"viewType":"B"
},{
"category":"Foods"
"subcat":"Meat"
"viewType":"C"
}
]
It's not exactly copy paste answer for you, but you need to create a data like data.
You need to modify data all together so for particular index with in single dictionary object you will get all data at once. If as your array will not have proper data then you app may crash if index will will not proper.
Then for particular index you can get viewType. you can compare it with required type and get the viewcontroller reference and push it.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if(options[indexPath.row]["viewType"] == "A") {
// Get A controller reference and use it
}else if(options[indexPath.row]["viewType"] == "B") {
// Get A controller reference and use it
}else if(options[indexPath.row]["viewType"] == "C") {
// Get A controller reference and use it
}
}
I hope you will understand the structure. Please, let me know if you are not clear.
Updated:
To get reference from storyboard,
let storyboard = UIStoryboard(name: "StoryboardName", bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: "someViewController") as! UIViewController
self.present(controller, animated: true, completion: nil)

pushViewController don't work when my tableView is in an TabBar

I have a TableViewController in a TabBar.
When I select one cell of my tableView, I want start a new controller with pushViewController(MyNewController).
This is my code :
In my TableView :
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let myController = (storyboard.instantiateViewControllerWithIdentifier("MyViewController") as? MyViewController)!
myController.parameter = self.tableau[indexPath.row]
UINavigationController().pushViewController(myController, animated: true)
}
In my TabBar :
func viewDidLoad() {
super.viewDidLoad()
var controllerArray: [UIViewController] = []
let controller: UIViewController = ClubPreviewListViewController()
controller.title = "TEST"
controllerArray.append(controller)
self.view.addSubview(pageMenu!.view)
}
(I use CAPSPageMenu for customize my TabBar, but it's not the problem, I have the same problem without)
In my controller :
deinit {
print ("TEST")
}
When I select a cell, the log write "TEST" everytime I select but don't change the view.
I think it's my navigationController the problem, but I don't know how to fix it.
Before I implement the TabBar, I use my TableView alone, and the push did works.
Sorry for my english ! Thanks for your help.
EDIT:
I change my pushViewController :
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let myController = (storyboard.instantiateViewControllerWithIdentifier("MyViewController") as? MyViewController)!
myController.parameter = self.tableau[indexPath.row]
//UINavigationController().pushViewController(myController, animated: true)
self.navigationController?.pushViewController(myController, animated: true)
}
Same reaction.
My NavigationController isn't directly link with my TabBar. I need to create an other one ? I don't really understand how NavigationController works !
This is my configuration
EDIT2:
If I use the navigationController of my TabBar and not of my TableView, the view change !
self.saveTabBarNavigationController.pushViewController(myController, animated: true)
You are creating an instance of a navigation controller on the line
UINavigationController().pushViewController(myController, animated: true)
Once this method finishes executing, the navigation controller and its view controllers will be deallocated because nothing retains your navigation controller. Causing 'TEST' to be printed in your deinit() function.
You should be obtaining the navigation controller that owns your current tab bar controller and pushing onto the stack using that. Without knowing the structure of your application it is difficult to know where your navigation controller is (if it exists).
Check your storyboard, but essentially try:
self.navigationController.pushViewController(myController, animated: true)
Try this it will work only if you have a navigation embedded tabbar controller
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let myController = (storyboard.instantiateViewControllerWithIdentifier("MyViewController") as? MyViewController)!
myController.parameter = self.tableau[indexPath.row]
navigationController.pushViewController(myController, animated: true)
}

How to push segue from cell click in table view to another view controller [duplicate]

This question already has answers here:
How to make a push segue when a UITableViewCell is selected
(10 answers)
Closed 6 years ago.
I have one table view controller and by clicking the cell i am redirecting the user to detail view controller.But when i perform segue " present view controller" its working fine.But what i need is?
I need to perform push segue by clicking the table view cell.How to do that?
Here is my code:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath){
let storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let vc: BusinessDetailViewController = storyboard.instantiateViewControllerWithIdentifier("BusinessDetailViewController") as! BusinessDetailViewController
vc.BusinessData = arrDict[indexPath.row]
self.presentViewController(vc, animated: true, completion: nil)
}
I have tried this below line :
self.navigationController?.pushViewController(vc, animated: true)
But it doesn't work.Any Solution Please !!
First of all your UITableViewController must have a UINavigationController
To do it rapidly embedded it to your table from the xCode menu
:
Then , you must create the segue, ctrl-drag from the UITableViewController to the destination viewController:
Then select the segue and give it an identifier in the property inspector:
Now you are able to perform this segue in code:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell = tableView.cellForRowAtIndexPath(indexPath)
tableView.deselectRowAtIndexPath(indexPath, animated: true)
performSegueWithIdentifier("mySegue", sender: cell)
}
If you are not using UINavigationController than add a segue in storyboard from table cell to destination viewController and give a identifier to segue.
then on cell click call
- performSegueWithIdentifier:sender:
and implement
- prepareForSegue:sender:
Without a navigation controller it's not possible to push a controller. Your self.navigationController property is nil (you can check it)
How to solve it?
A :You need to embed your view controller in navigation controller either via code or via storyboard
try this code, its working for me,
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath){
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let controller = storyboard.instantiateViewControllerWithIdentifier("PlayViewController") as! PlayViewController
self.navigationController?.pushViewController(controller, animated: true)
}
and set the storyboard Id, example given below,
hope its helpful

How to instantiateViewControllerWithIdentifier from inside UITableViewCell Controller

The goal is to create a new view controller from inside a custom UITableViewCell function. All the examples I've seen do this from within a UIVIewController.
How should this be accomplished?
This is the full controller for the custom table nib.
import UIKit
class feedRow: UITableViewCell {
#IBAction func tapThing(sender: AnyObject) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
var vc:UIViewController!
// THIS DOESN'T WORK:
self.thingController!.pushViewController(storyboard!.instantiateViewControllerWithIdentifier("thingDetail") as UIViewController, animated: true)
}
}
The error is "'feedRow' does not have a member named 'thingController'"
Since this is within UITableViewCell, it therefore doesn't include controls present in UIViewController that other examples show.
UPDATE: Per the answer, this was moved to the didSelectRowAtIndexPath section.
func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
var goThing = storyboard.instantiateViewControllerWithIdentifier("thingDetail") as UIViewController
self.presentViewController(goThing, animated:true, completion:nil)
}
Call it in your view controller class where is your tableview in function didSelectRowAtIndexPath it should work.

How to change view when tapping button in a custom UITableViewCell

Usually, I change view like this:
var goBackToMainView:MainViewController = self.storyboard?.instantiateViewControllerWithIdentifier("navigation2") as MainViewController
self.presentViewController(goBackToMainView, animated: true, completion: nil)
But if I try to do this in my custom UITableViewCell when the user tap a button, it gives me errors like customTableViewCell does not have a member named 'storyboard' and 'presentViewController'
How can I change views in my TableViewCell ?
Have you tried adding as a subview?
Example:
var tableViewCell = UITableViewCell(frame: aFrame)
tableViewCell.addSubview(aView)
Why do it in the UITableViewCell subclass? You should be doing your view management in the ViewController.
In your view controller:
import UIKit
// Take note of UITableViewDelegate, you'll need it to be able to use
// tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
class MyTableViewController: UITableViewController, UITableViewDelegate {
// Assuming that you have a storyboard variable in AppDelegate
let appDelegate: AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
// .. more code here like viewDidLoad, etc.
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
var viewController = appDelegate.storyboard.instantiateViewControllerWithIdentifier("MainViewController") as MainViewController
// This will probably appear as a modal
self.presentViewController(viewController, animated: true, completion: nil)
}
}
Note: I just did a quick playground for the code above so you may need to unwrap optionals.
If you have your view controller embedded in a navigation controller, you might want to use Unwind Segues. More information about that here: What are Unwind segues for and how do you use them?
Cheers!

Resources