I have a tableview with cells which trigger a segue when selected, taking me to the next view. Everything happens perfectly if I put break-points in the code.
TableView is not the first View in the app. It's is loaded via a segue from the Main Screen of the app via an on-screen button, which surprisingly doesn't exhibit this behaviour(single click works fine first time itself).
However, I need to click a cell "twice"(time difference between the clicks doesnt matter) to select it first time when there are no break-points. Thereon, single clicks are fine. Testing this on my Xcode iPhone simulator.
My Code -
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
// Keep track of the Holding selected
self.selectedHolding = self.portfolio.holdings[indexPath.row]
// Trigger the segue to the detail view
self.performSegueWithIdentifier("toHoldingTransactionsSegue", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let actualIdentifier = segue.identifier {
if actualIdentifier == "toHoldingTransactionsSegue" {
let holdingTransactionsViewController = segue.destinationViewController as HoldingTransactionsViewController
holdingTransactionsViewController.holding = self.selectedHolding
holdingTransactionsViewController.delegate = self
}
}
}
Please help.
You should connect the segue to the view controller instead of to the cell. When you connect the segue to the cell directly it bypasses / interferes with didSelectCellAtIndexPath
Related
Back Button shows in StoryBoard but not Simulator.
I added a segue from TableViewController to DetailViewController to pass data. The Storyboard automatically shows a Back Button on DetailViewController, but when I run the Simulator, the button doesn't show up.
This is my Storyboard:
A closer look of TableViewController and DetailViewController:
But in my Simulator the button doesn't show up:
The hierarchy of the whole project:
I want to know where to configure the back button(in my segue?), or instead deleting the button(not letting it show in the Storyboard) so I can create one myself.
The code of my segue in my TableViewController:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "showDetailView", sender: indexPath)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
switch (segue.destination, sender) {
case (let controller as DetailViewController, let indexPath as NSIndexPath):
controller.receivedName = storeList[indexPath.row].name!
controller.receivedDesc = storeList[indexPath.row].desc!
controller.receivedRate = storeList[indexPath.row].rate
controller.receivedUrl = storeList[indexPath.row].url!
default:
print("unknown segue")
break
}
}
Your initial view controller in the storyboard is actually the TabelViewController (you can see there is an arrow to it).
Thats' why when you start the scene and the TableViewController shows but it is not embedded in the navigation because the navigation controller has never been created.
Just change which is the initial view controller to be the navigation controller or any other before the navigation controller which holds the TableViewController.
You can just drag the arrow to change the initial controller in the storyboard
I am looking at using a collectionView for a menu within an app. I want the menu to have a navigation controller so the user knows they're in the menu and can go forwards and back between the menu and the page selected from the menu.
However as i have created the collectionView programatically i don't seem able to use a 'show' segue as the cells are created at runtime.
Interface
Runtime
Is there a way of still utilising the navigation bar for this menu?
I was previously using a static tableview with segue from each cell to desired page. Ive got a bunch of code tied into each named segue so am reluctant to change.
Code using segues on the old tableview
class MenuTable: UITableViewController {
weak var centerButtonDelegate: ManageCenterButtonDelegate?
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "segueTour" {
fadeOutDelegate()
}
I think you should perform the segue programatically if you are linking a UICollectionViewCell to a new ViewController, they are way more easy to control, might be as well that you set it wrong in the storyboard too.
In your tableView delegate method 'selectedRowAt: IndexPath' you should do a switch statement and perform the segue there. Something like this:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
switch indexPath.item {
case 0:
//perfrom segue
performSegue("mySegue", sender: self)
default:
break
}
}
When the cell is selected or tapped (or however you want to detect this), create the next view controller and configure it appropriately to that cell, and call show.
I have two segues from one ViewController.
One is supposed to run(crashes for now) when clicking on LogOut Button (Go to LogIn ViewController), another one runs(works good) when clicking on thumbnail of a video.
Since I need to retrieve the video from the server and display it in the ViewController I'm heading to(WatchVideoViewController), I do the code below:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get a reference to a destination View Controller
let detailViewController = segue.destinationViewController as! WatchVideoViewController
// Set the selected video property of the destination view controller
detailViewController.selectedVideo = self.selectedVideo
}
As you might guess this code runs when performing every segue, that's why my LogOut segue crashes.
Could not cast value of type 'AppName.LoginViewController' to 'Appname.WatchVideoViewController'.
Here are pieces of code where I call segues:
#IBAction func pressLogOutButton(sender: AnyObject) {
self.performSegueWithIdentifier("logOutSegue", sender: self)
}
// Handle event when user selects a cell(thumbnail)
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
// Take note of which video is selected
self.selectedVideo = self.videos[indexPath.row]
// Call the segue
self.performSegueWithIdentifier("goToVideo", sender: self)
}
Is there any way to avoid running prepareForSegue when calling pressLogOutButton? Thanks a lot!
Check in your prepareForSegue
if segue.identifier == "logOutSegue"
// perform log out logic
I have a Tab Bar application, and one of the tabs, which contains a Table View, segues into a third view when a table cell is pressed. The view controller acts as a delegate for the UITableView, and I trigger the segue programatically as follows:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
println("cell tapped, starting segue")
performSegueWithIdentifier("showDetails", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
println("prep for segue")
// TODO - more code here
}
Finally, I set up the following code to debug the problem with the third view:
class DetailsViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
println("did load")
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
println("will appear")
}
}
The problem is that when I press a table cell for the first time, the viewWillAppear function never gets called until I interact with the UI in some way (e.g. just a tap anywhere on the screen). The view that I want to segue into doesn't show up, as if the screen didn't get refreshed. However, when I tap the screen, the whole animation runs and I can segue as intended. This is my output when I tap a cell:
cell tapped, starting segue
prep for segue
did load
I tried to find solutions online, but all the issues I found it seems to just not work at all. In my case, it is working, but not immediately.
In case it helps, here's a screenshot of my storyboard:
Sefu found the answer and posted it in the comments, I ran into the same issue and his solution worked for me. The trick is to make it so the cell that is selected that triggers the segue needs to have a selection style set (not None), and I also found that deselecting the cell in tableView:didSelectRowAtIndexPath: also needed to happen.
Ran into a similar problem while having my selectionStyle = .None .
An option you can use, if you're like me and don't want a selectionStyle applied is to set the cell item back to unselected in the prep for segue.
That seemed to stopped the 'issue' I was seeing where the segue would work perfectly once, but all subsequent calls would require selecting the cell twice.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
//sending the index path up as the sender so the prep for segue can access the cell
self.performSegueWithIdentifier("segueID", sender: indexPath);
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "segueID"){
if let indexPath : NSIndexPath = sender as? NSIndexPath{
tableViewReference.cellForRowAtIndexPath(indexPath)?.selected = false;
let destinationVC : UIViewControllerClass = segue.destinationViewController as! UIViewControllerClass;
destinationVC.customMethod(/* some value */);
}
}
}
I was following this tutorial http://www.raywenderlich.com/76519/add-table-view-search-swift when I ran into an error. I am adding this feature into an app I was already working on. Once I am in the booths table view, I want to be able to navigate out into the main menu with a button on the navigation bar. Here is the section of code that deals with the segues.
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("BoothDetail", sender: tableView)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if segue.identifier == "BoothDetail" {
let BoothDetailViewController = segue.destinationViewController as UIViewController
if sender as UITableView == self.searchDisplayController!.searchResultsTableView {
let indexPath = self.searchDisplayController!.searchResultsTableView.indexPathForSelectedRow()!
let destinationTitle = self.filteredBooths[indexPath.row].name
BoothDetailViewController.title = destinationTitle
} else {
let indexPath = self.tableView.indexPathForSelectedRow()!
let destinationTitle = self.booths[indexPath.row].name
BoothDetailViewController.title = destinationTitle
}
}
}
}
The error is thrown while trying to use the back button on the booths list that is a direct show segue to the main conference menu. The error is on this line.
if sender as UITableView == self.searchDisplayController!.searchResultsTableView {
You have quite a few problems. Some fatal, some just a headache.
the first headache is you are calling the same segue twice. Both functions call the same segue. Both will execute. Now if you want a double animation, okay. But since one passes data and the other does not, you may have an issue. Eliminate the didSelectRowAtIndexPath function.
In your prepareForSegue method it appears you have two different objects connected to the same segue. A searchDisplayController and a tableView. You want two separate segues. Then your if/else makes changes based on which segue was chosen:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "segue1" {
//code set 1
} else if segue.identifier == "segue2" {
//code set 2
}
}
I had similar problem and I just got it solved. When creating your segue in the tableview do not drag it from the cell, create a manual segue called "BoothDetail"
and connect it to BoothDetailViewController, to create a manual segue select the table view controller and click on "show connection inspector" you will see manual under triggered segue .
My problem the sender was a tableviewcell and not the tableview, so the function
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("BoothDetail", sender: tableView)
}
was never called to pass the tableview controller so when you try to cast it you were getting the error.
good luck