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)
Related
I'm trying to push from viewcontroller with tableview to another view with tableview too,
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("Clicke\(indexPath.row)")
guard let vc = storyboard?.instantiateViewController(withIdentifier: "SecAdsViewController") as? SecAdsViewController else { return }
vc.data = data[indexPath.row]
self.navigationController?.pushViewController(vc, animated: true)
}
the code is looking good, storyboard id is correct too but it is not pushing when I click on the cell and no action, console response is good too
breakpoint has no issues!
my story board
As you mention in the comment the best solution is to create a new storyboard.
Try this
let storyboard = UIStoryboard(named: "Sections", bundle: "nil")
guard let vc = storyboard.instantiateViewController(withIdentifier: "SecAdsViewController") as? SecAdsViewController else { return }
vc.data = data[indexPath.row]
self.navigationController?.pushViewController(vc, animated: true)
This solution assumes you don't have a NavigationController in Sections storyboard, which is something you would not want in any case as you already have a NavigationController in the other storyboard.
I have a storyboard with tabbarcontroller. One of tab bar has a tableview and I want that when the user tap in a row from tableview open a detail view with another tabbar. The problem is when I open detail view tab bar hides . how to show tabbar at didselectrowatindexpath?
The code in didselectrowatindexpath:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let storybaord=UIStoryboard(name: "Main", bundle: nil)
let DVC=storybaord.instantiateViewController(withIdentifier: "NewsViewController") as! NewsViewController
DVC.getImage=sneaker[indexPath.row]
DVC.getNews=News[indexPath.row]
self.navigationController?.pushViewController(DVC, animated: true)
}
I have created single view application.I have created DiscoveryNewsTableViewCell.I populated the table view cell with two arrays 1-sneaker 2- News array .I want when the particular array displayed ist tab of bar controller .But i did get these fields on first tab of tabbar controller .Here is the sample code for this https://drive.google.com/file/d/1uSYl-4a1UQXpMXkSQ_l8aij6EH_v2yna/view?usp=sharing
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// setting these values in local storage using user defaults
let currentObj = News[indexPath.row]
UserDefaults.standard.set(currentObj, forKey: "currentOb")
let storybaord=UIStoryboard(name: "Main", bundle: nil)
let DVC=storybaord.instantiateViewController(withIdentifier: "NewsViewController") as! NewsViewController
self.navigationController?.pushViewController(DVC, animated: true)
}
This is happening because you are pushing the viewController instead of TabBarController.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let storybaord=UIStoryboard(name: "Main", bundle: nil)
let tabBar=storybaord.instantiateViewController(withIdentifier: "tabBar") as! UITabBarController
let DVC = tabBar.viewControllers[0] as! NewsViewController
tabBar.selectedIndex = 0
DVC.getImage=sneaker[indexPath.row]
DVC.getNews=News[indexPath.row]
self.navigationController?.pushViewController(tabBar, animated: true)
}
In the above code replace 0 in
tabBar.viewControllers[0]
tabBar.selectedIndex = 0
with index of view controller you want to open.
And also in the line
let tabBar=storybaord.instantiateViewController(withIdentifier: "tabBar") as! UITabBarController
tabBar has to be set as storyboard identifier for UITabBarController that you want to display as shown below.
I am working at my first application in Swift 3. I am using tableView (by "extension MainController: UITableViewDataSource"). And from this tableView, by storyboard I have two segues. One for editing (by clicking on accessory icon) and the second one for more detail screen (by clicking on a table row). I am not calling this segues by code, but by storyboard.
And my problem is that there is sometimes huge lag. Like after clicking on a row, the next screen is showing after 30 seconds. But now always. Sometimes its working immediately. Interesting thing is that when I touch row 1, and nothing happens, next I am clicking row 2 and then row 1 is appearing.
I am also using delegates, this is the code for preparing segues:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// 1
if segue.identifier == "AddSensor" {
// 2
let navigationController = segue.destination
as! UINavigationController
// 3
let controller = navigationController.topViewController
as! AddController
// 4
controller.delegate = self
}
else if segue.identifier == "EditSensor" {
let navigationController = segue.destination
as! UINavigationController
let controller = navigationController.topViewController
as! AddController
controller.delegate = self
if let indexPath = tableView.indexPath(
for: sender as! UITableViewCell) {
controller.sensorToEdit = sensors[indexPath.row]
}
}
else if segue.identifier == "DetailSeq" {
let navigationController = segue.destination
as! UINavigationController
let controller = navigationController.topViewController
as! DetailController
controller.delegate = self
if let indexPath = tableView.indexPath(
for: sender as! UITableViewCell) {
controller.sensorRecieved = sensors[indexPath.row]
}
}
}
I was reading that it was common bug in iOS8 and could be resolved by adding
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
DispatchQueue.main.async {
self.performSegue(withIdentifier: "DetailSeq",sender: self)
}
}
But it didn't worked for me. I don't know what should I do next to resolve this problem. Can anyone guide me?
According to this SO question, you may be able to fix your bug if you present your view controller in code rather than with the segue in the storyboard. Something like this, where your destination is the VC that you want to go to.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath:
NSIndexPath) {
DispatchQueue.main.async {
self.presentViewController(destination, animated: true) { () -> Void
in
}
}
}
You have to use like this :
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
DispatchQueue.main.async {
self.performSegue(withIdentifier: "DetailSeq",sender: self)
}
}
I have a problem.
I need help. I have been looking for a solution for about 5 hours. Unfortunately without success.
My problem is that I have several storyboards and created without Segue.
I would love the selected Tableviewcell title pass to rootViewController.
Here is my code in my ModalViewTable:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
let indexNumber = "\(indexPath.row)"
let indexPath = tableView.indexPathForSelectedRow
let currentCell = tableView.cellForRow(at: indexPath!) as UITableViewCell!
let storyboard = UIStoryboard(name: "addTime", bundle: nil)
var viewController = storyboard.instantiateViewController(withIdentifier: "addTimeVC") as! addTimeViewController
viewController.test = "TESTABCDEF"
passedValue = ("\(indexNumber)")
dismiss(animated: true, completion: nil)
}
I have a property test in my firstViewController. What is here wrong?
I've also tried with delegates and closures but without success. Please help me.
Try this instead:
let indexNumber = "\(indexPath.row)"
let indexPath = tableView.indexPathForSelectedRow
let currentCell = tableView.cellForRow(at: indexPath!) as UITableViewCell!
let viewController = navigationController!.presentingViewController as! addTimeViewController
viewController.test = "TESTABCDEF"
passedValue = ("\(indexNumber)")
navigationController!.dismiss(animated: true, completion: nil)
When you present a view controller modally using the present(_:animated) method, the view controller that was presented has the presentingViewController property set to the view controller that presented it. In other words, this property contains a reference to the previous view controller.
I want to present a different view when selecting each Cell in a Table View.
I figured out that I have to use this function:
func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
}
What should I add inside the function to make this work?
First of all, you need didSelectRowAtIndexPath and inside the function you could use indexPath.row to know witch cell was tapped and then you need to create and push the view you want
let viewControllerObj = self.storyboard?.instantiateViewControllerWithIdentifier("ViewControllerIdentifier") as? ViewController
self.navigationController?.pushViewController(viewControllerObj!, animated: true)
also, make sure your navigationController is not nil
...hope it helps
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
if indexPath.row == 0
{
let objOne = self.storyboard?.instantiateViewControllerWithIdentifier("ID_OneScene") as? OneScene
self.navigationController?.pushViewController(objOne!, animated: true)
}
else if indexPath.row == 1
{
let objTwo = self.storyboard?.instantiateViewControllerWithIdentifier("ID_TwoScene") as? TwoScene
self.navigationController?.pushViewController(objTwo!, animated: true)
}
else
{
let objOther = self.storyboard?.instantiateViewControllerWithIdentifier("ID_OtherScene") as? OtherScene
self.navigationController?.pushViewController(objOther!, animated: true)
}
}