0

I need help with pushing my tableView to a detailView. Right now I have most of the code, but right when my app loads, it goes to the detailedView, and whenever I try to go back to the tableView, it instantly goes back to the detailedView and the following error shows up in the debug area:

Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted.

I don't understand why this is happening since my code is not in the viewDidLoad section of the code... Here is my code for the tableView:

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    return Label.count

}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    var cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")

    cell.textLabel.text = Label[indexPath.row]

    performSegueWithIdentifier ("showDetail", sender: self)
    func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {

        if segue.identifier == "showDetail" {


        }

    }

    return cell

}

Please leave an answer below if you can help me make my segue work how it is supposed to. Thanks!

P.S. I am also curious on how to customize the back button on a navigation bar from "< Back" to just "<".

P.S.S. How can I make the tableViewCell auto release after pressed so it doesn't stay highlighted? Just so it looks like a nicer app overall.

P.S.S.S Sorry, but one last thing is how can I customize the DeatilView based on what cell the user clicks on? I already have the new class set up with text, but not sure how to make the if statement that customizes the text for each cell clicked.

Thanks again!

Greg
  • 93
  • 1
  • 10

3 Answers3

3

The error is in your cellForRowAtIndexPath:

performSegueWithIdentifier ("showDetail", sender: self)

this triggers the segue when the cell is displayed, not when it's selected. The easiest way to fix that is to create a segue in IB from the cell to the destination view controller.

Also, this code:

func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
    if segue.identifier == "showDetail" {
    }    
}

creates a function local to cellForRowAtIndexPath which is never executed. The correct way is to declare it in the class scope as an override of the superclass implementation.

If you have already defined a segue in IB, then your code should like:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    var cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
    cell.textLabel.text = Label[indexPath.row]
    return cell
}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "showDetail" {

    }
}
Antonio
  • 71,651
  • 11
  • 148
  • 165
  • I have a segue named showDetail in IB, but am still getting this error. What do you suggest I change? I am not understanding what you are advising me to change, sorry. Can you show me what code to use please? I am also getting this error if it helps: nested push animation can result in corrupted navigation bar – Greg Nov 17 '14 at 21:14
0

you have to perform the segue in tableView(_:didSelectRowAtIndexPath:) not tableView(_:cellForRowAtIndexPath:)

vikingosegundo
  • 52,040
  • 14
  • 137
  • 178
  • It works now! Thank you so much! And sorry to be a pain, but do you know how to solve the questions I said in the P.S and P.S.S? And also how to customize the DetailedView based on what cell the user clicks on? I know how to do this in ObjC, but trying to learn in Swift. (I just added this to the original question as well) – Greg Nov 17 '14 at 21:22
0

P.S. How to customize the back button on a navigation bar from "< Back" to just "<".

I found this old question has the answer in Objective C, at How to change text on a back button

You must set this in the View Controller you are segueing from.

Let's say we have a simple iPhone app, that has a UITableViewController with a bunch of cells listing off numbers, let's call it the "NumberListTVC". We embed this NumberListTVC in a NavigationController. We set a selection segue on one of the cells to another ViewController, which we'll call the "NumberDisplayerVC". This NumberDisplayerVC has one label, which we will set to the contents of the label that was clicked on the NumberList. So when you select a cell in NumberListTVC, it will push to the "NumberDisplayer" in the NavigationController.

So for this app, you would put the code to customize the back button in the NumberListTVC, so that when you are looking at the NumberDisplayerVC, it will show the back button we want it to, instead of the default (since the back button brings it back to the NumberListTVC).

In Objective-C, as per the linked answer, the code to change "< Back" to "<" would be:

self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];

Basically, we create a new UIBarButtonItem with whatever title we want. In this case, I just gave it the title of "", which is just an empty String.

The same command in Swift would be:

self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style:.Plain, target: nil, action: nil)

I put this in NumberListTVC's viewDidLoad method, to make sure it was ran when NumberListTVC loaded.

P.S.S. How can I make the tableViewCell auto release after pressed so it doesn't stay highlighted?

This is covered in Objective-C on the answer Selected UItableViewCell staying blue when selected

You just have to tell the UITableViewCell to deselect it in its didSelectRowAtIndexPath.

In Objective-C, you would override it and do this: - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { //Do whatever else you want to do here... [tableView deselectRowAtIndexPath:indexPath animated:YES]; }

The Swift code would be similar:

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
    //Do whatever else you want to do here...

    tableView.deselectRowAtIndexPath(indexPath, animated: true)
}

P.S.S.S How can I customize the DetailView based on what cell the user clicks on?

For simplicity's sake, I am going to use my first example which is just using our navigationController with the NumberListTVC and NumberDisplayerVC, so not on a UISplitView, but the question asked affects either scenario.

Basically, you have to get what you want from the cell that was clicked on, and then set it to whatever you want to use it in the next ViewController. So, in your prepareForSegue, you would do something like this:

if segue.identifier == "amazingSegue"
{
    if let cellText = (sender as? UITableViewCell)?.textLabel.text
    {
        if let someVC = segue.destinationViewController as? NumberDisplayerVC
        {
            someVC.textToDisplay = cellText
        }
    }
}

This is basically what Antonio said in his answer. I added a bit more to it. So in my case, the NumberListTVC is a bunch of dynamically created UITableViewCells. I want to grab the label out of each one and then use that in the NumberDisplayerVC. So we:

  1. Check if it is the segue we want to actually work with, in this case the segue between NumberListTVC and NumberDisplayerVC is named "amazing segue".
  2. Next, use optional binding to assign the text of the sender cell to the constant cellText. We use the optional type cast operator to check if the sender is a UITableViewCell. We then use optional chaining to look inside this UITableViewCell and extract the text from its textLabel.
  3. Again use Optional Binding to assign our destinationViewController to the constant someVC. We optionally type cast it to a NumberDisplayerVC, which is what it should be. If it indeed is one, it will correctly bind to the someVC variable.
  4. Then just set the textToDisplay property to the cellText constant we optionally bound earlier.

I'm not sure if this is the best way, I don't feel great about the tower of if let statements, but it does the job initially.

Community
  • 1
  • 1
NickH
  • 683
  • 1
  • 5
  • 24