I have tableViewController which pulls data from Parse. This calls inherits from UINavigationControllerDelegate.
I want to push a new view controller when the user taps on a cell. It seems like a simple task but I can't get it to work. I have first tried just simply making a push segue in my storyboard but nothing happens when I tap on the cell. I have tried to do it programmatically but the app crashes when I tap on the cell. I get a breakpoint error on the instantiation line:
import UIKit
import Foundation
import Parse
class PFViewController: PFQueryTableViewController, UITableViewDataSource, UINavigationControllerDelegate {
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let vc: Podcast = self.storyboard?.instantiateViewControllerWithIdentifier("Podcast") as Podcast
self.navigationController?.pushViewController(vc, animated: true)
}
}
Any ideas please?
To create the segue, ctrl-drag from the TableViewController 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)
}
Related
I have a screen with this view hierarchy.
I have tableview inside collectionview, and in that tableview, I have reusable cell.
I want to implement navigationController.pushViewController() when I tap tableview cell which is located in collectinview cell(and of course this collection view cell is in collectionview).
So I tried to create delegate protocol inside collection view cell which holding tableview.
protocol PushViewControllerDelegate {
func pushViewController()
}
class CollectionViewCell: UICollectionViewCell, UITableViewDelegate, UITableViewDataSource{
var delegate: PushViewControllerDelegate?
var tableView = UITableView()
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
delegate?.pushViewController()
}
}
And In the ViewController which hold all of these view hierarchies, wrote like :
class MainViewController: UIViewController, PushViewControllerDelegate {
let customCell = CollectionViewCell()
override func viewDidLoad() {
super.viewDidLoad()
customCell.delegate = self
}
func pushViewController() {
let vc = SecondVC()
navigationController?.pushViewController(vc, animated: true)
}
}
But this delegate method is not calling when I tap tableview cell.
How can I navigate using pushViewcontroller in my situation?
In a table view controller, I'm trying to get the index of the row that is selected before I segue (will pass this info in prepare for segue eventually). I have implemented this function:
var selectedQuestionCell: IndexPath?
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
selectedQuestionCell = indexPath
}
This was working great for me initially. I was able to snag the index of the selected row in my table. However, I want to perform a segue when a row is tapped which will transfer to another View. I connected a segue to my cell (dynamic prototypes). After connecting a segue, my override function no longer executes! I'm really new to Table View Controllers, so I'm not sure if there's anyway I can manually execute this.
To summarize: my problem is after connecting a segue to my cells, the override function to get their index is no longer called. How can I fix this?
Try these thing
Create a new segue from your tableview to another view and name it as you like.
Now add this code inside your didSelectRowAt
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let viewController = storyboard?.instantiateViewController(withIdentifier: "your_segue_name_here") as! YourViewControllerName
self.navigationController?.pushViewController(viewController, animated: true)
}
Please make sure that your tableview is connected with navigation controller.
To do that select your tableView then click on Editor -> Embed In -> Navigation Controller from your Xcode.
I hope it works for you.
: D
I am writing a Xcode program in Swift. I have a tableview controller with some labels and an image per cell. They have their data from a first view controller. So far so good. Now i would like the user to tap a cell which opens a new controller which contains the same label and image data as the cell. With the following code the new controller opens, nonetheless I don't no how to transfer the data. If someone could help me I would be so so grateful.
Here are the codes that i tend to use:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellIdentifier = "TableView"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! TableView
let picture = pic[indexPath.row]
cell.label1.text = picture.name1
cell.photoImage.image = picture.photo
cell.label2.text = picture.name2
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
let cell = indexPath.row
self.performSegueWithIdentifier("segue", sender: cell)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "segue"{
var row = tableView.indexPathForSelectedRow
let viewController = segue.destinationViewController as! vc2
}
}
PS:I have a segue from the image to the new controller with the identifier "segue".
PPS: Of course i have tried the following method: Send data from TableView to DetailView Swift but when i run my program I get an error with the information that my labels were unexpectedly found nil
You should not need to override didSelectRowAtIndexPath or call performSegueWithIdentifier to do this. Connect your segue in the IB file dragging from a table view controller's cell to the second controller. You should then pass the data to the controller in prepareForSegue, in the segue.destinationViewController. You set the public properties on that destination controller.
Also make sure your labels in your prototype cell have been connected in IB. If they are they, should not be nil. Set a breakpoint on the cellForRowAtIndexPath to verify this.
Unless you are talking about the labels in your destination controller. These also need to be hooked up in IB. You would then set them in prepareForSegue. You would get the appropriate data from the
let viewController = segue.destinationViewController as! vc2
var path = tableView.indexPathForSelectedRow
viewController.destLabel.text = arrayData[path.row].myData // or whatever data you have from your model.
I am having an issue with designing a storyboard. I currently have an app in the app store that was designed with XIB files. I have a tableView placed on a UIViewController - not a tableViewController - that loads a unique viewController for each row that is selected.
I am trying to convert this concept to a storyboard. I've done the following
Place a UIViewController in the Storyboard.
Place a UITableView on the UIViewController so I can customize the table view.
I tried making connections to multiple ViewControllers from the UITableViewCell and I am not allowed.
I tried creating multiple segues from the UIViewController - which I can - but when I click on the cells the segues are not fired. I tried using didSelectRowAtIndexPath: and prepareForSegue:
Since this did not work I tried creating a project with a UITableViewController and then created multiple segues from the UITableViewController. I then named each segue and used the didSelectRowAtIndexPath: method to test the selected cell and called performSegueWithIdentifier: and this did not work. As I clicked on cells I would get random loading of the incorrect viewController. I've copied a bit of my code and few screen shots below.
I am wondering if I am blatantly missing something obvious or do I have to revert to a xib format for this type of project?
override func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath)
{
if indexPath.row == 0
{
println("Segue1")
self.performSegueWithIdentifier("Segue1", sender: self)
}
else if indexPath.row == 1
{
println("Segue2")
self.performSegueWithIdentifier("Segue2", sender: self)
}
else if indexPath.row == 2
{
println("Segue3")
self.performSegueWithIdentifier("Segue3", sender: self)
}
}
Take care,
Jon
The method
override func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) is called when an item is deselected.
To call a method when an item is selected, change the method name to override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
I used a combination of the comment by Allen. Initially I wasn't able to create the segues I needed. I created a navigation controller that uses my own view controller that holds a tableview. Then I created the associated cells for the prototype cells and switched them to a static cell. I only have a limited amount, 3 at the time. This allowed me to created the segues to the appropriate views in the storyboard. Then I changed the cells back to prototype cells and it maintained the connection to the segues. All that is left was creating the associated switch statement in the table view to go to the correct segue. Just make sure you name your segues with the identifiers listed in your code.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath:NSIndexPath) {
//Add cases here to move to different segues
switch indexPath.row{
case 0: self.performSegueWithIdentifier("courses", sender: self);
break;
case 1: self.performSegueWithIdentifier("finals", sender: self);
break;
case 2: self.performSegueWithIdentifier("academic", sender: self);
break;
default:
break
}
}
Swift 3 Code
Well, look at my piece of code I use to perform dynamic segue based on the type of the device type in the cell. :) Hope it helps.
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let device = Cache.DEVICELIST[indexPath.row]
let deviceType = device.type
switch deviceType {
case "camera":
self.performSegue(withIdentifier: "DashCellToCamera", sender: self)
case "gateway" :
self.performSegue(withIdentifier: "DashCellToGateway", sender: self)
case "tracker" :
self.performSegue(withIdentifier: "DashCellToTracker", sender: self)
case "panicbutton" :
self.performSegue(withIdentifier: "DashCellToPanicButton", sender: self)
default:
break
//do nothing just ignore this
}
}
I have 1 viewController and 1 tableViewController in swift. I can send an NSMutableArray from the viewController to populate the tableViewController using segue. I do not know how to send the selected row back to the view controller. The code so far:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
println("You selected cell #\(indexPath.row)!")
// Missing code for sending back the selected row
self.dismissViewControllerAnimated(true, completion: nil)
}
Any ideas?
You can use the delegation pattern. Create a protocol:
protocol MyDataDelegate {
didSelectRow(row: NSIndexPath, data: MyData)
}
In the table controller, add a property:
var myDataDelegate: MyDataDelegate?
and in the didSelectRowAtIndexPath call the delegate method:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
println("You selected cell #\(indexPath.row)!")
let data = getDataForRow(indexPath) // <== You need to implement it
self.myDataDelegate?.didSelectRow(indexPath, data: data)
self.dismissViewControllerAnimated(true, completion: nil)
}
Next, in your main view controller:
implement the MyDataDelegate protocol
implement the MyDataDelegate.didSelectRow method
right before presenting the table controller (or after creating it, if you manually do it), set the myDataDelegate property of the table controller to self
This way, when a row is selected in your table controller, the didSelectRow method is called on your main view controller, so you can do whatever you need with the index path and/or the data.
Of course feel free to change the didSelectRow signature (use the indexpath, or a row index, with or without data, etc.)