Nested push animation, but there's no push? - uitableview

I am getting this error when I try to preform a segue...
2012-11-14 20:24:54.133 MyApp[26266:c07] nested push animation can result in corrupted navigation bar
2012-11-14 20:24:54.486 MyApp[26266:c07] Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted.
2012-11-14 20:24:54.487 MyApp[26266:c07] Unbalanced calls to begin/end appearance transitions for <SheetDrillDownViewController: 0xa1bb980>.
Here is my setup: Initial view --> next view (UITableView) --> last view (UITable)
Each cell pushes to another view until the last view. I do not have a modal segue, i have a push segue... I have the push segues linked from the cell to the next view, each with different names... I have a perform segue line in my selectedRowAtIndex method. I have tried removing that method, with people saying I am double calling the segue, but then the cell when clicked turns blue, and doesn't push to anywhere... How can I fix this error? Thanks.
Here is my code:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath) {
[self performSegueWithIdentifier:#"subjectDrillDown" sender:nil];
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSLog(#"Attempting to identify segue...");
// Make sure we're referring to the correct segue
if ([[segue identifier] isEqualToString:#"subjectDrillDown"]) {
NSLog(#"Segue has been identified...");
// Get reference to the destination view controller
SubjectDrillDownViewController *vc = [segue destinationViewController];
NSInteger selectedIndex = [[self.tableView indexPathForSelectedRow] row];
NSMutableDictionary *object = [tableDataSource objectAtIndex:selectedIndex];
NSString *key = [object valueForKey:#"key"];
[vc setSelectedItem:key];
NSLog(#"Switching to %# detail view...",key);
NSLog(#"Passing dictionary to %# view... (Source below)\n\n %#",key,[NSString stringWithFormat:#"%#", [tableDataSource objectAtIndex:selectedIndex]]);
[vc setDetailDataSourceDict:[tableDataSource objectAtIndex:selectedIndex]];
}
else {
NSLog(#"ERROR, DOUBLE CHECK SEGUE'S NAME!");
}
}
I have seen all of the other Stack Overflow questions, but most of the correct answers don't work for me...
EDIT:
The next view is able to load, but when I click the back button, there are suddenly two more views...
UPDATE:
I will try to post the number of times Attempting to identify segue... NSLogs, but my compiler suddenly won't run :(

You surely don't need to perform segue in didSelectRowAtIndexPath, if you have already configured it like cell -> next view.
But, removing the call from there doesn't work for you then you can try the segue from view controller (ctrl+drag from view area) to next view and keep the segue call in didSelectRowAtIndexPath
I always use one of the following methods
Method 1:
Segue from UITableViewCell to Next View Controller
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Nothing
}
Method 2:
Segue from Main View Controller to Next View Controller
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self performSegueWithIdentifier:#"subjectDrillDown" sender:nil];
}
The error you are getting is because you have segue and you perform the segue manually when selected - hence, it is resulting in nested push animation
Make sure the name of the segue is correct and you are using ONLY one of the above methods

Related

Segue to same view Controller loads before prepareforsegue is called

Hi guys i am a beginner on Obj c Programming, I have created a "self segue"(segue to same view controller) from a tableviewcell. Now my problem is, i am setting few parameters in the prepareForSegue method, but somehow the segue already happens before this method is called(i am not even calling "performSeguewithIdentifier"). I understand that this might be because the segue is associated with the cell. But i found no other way to create a "self-segue"
please help.Btw i am using xcode6..
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
_selctdObj = [avObjArray objectAtIndex:indexPath.row];
if([_selctdObj isContainer])
{
[self performSegueWithIdentifier:#"isContainerSegue" sender:self];
}
else
{
[self performSegueWithIdentifier:#"isItemSegue" sender:self];
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"isContainerSegue"]) {
// Get destination view
serverBrowseVC *sbvc = [segue destinationViewController];
[sbvc setServerSelected:_serverSelected];
[sbvc setBrowseObjID:_selctdObj];
}
}
Now invariably "isContainerSegue" gets executed ,even is the object is not a container. i also tried commenting the
//[self performSegueWithIdentifier:#"isContainerSegue" sender:self];
But every time "isContainerSegue" gets executed..
You said you weren't calling performSegueWithIdentifier, but you are. You shouldn't be if you've connected the segue from the cell. You also shouldn't implement didSelectRowAtIndexPath at all, just prepareForSegue. You can get the indexPath from the sender argument (the sender will be the cell) of prepareForSegue:sender:. If you're having a problem with the "if [_selctdObj isContainer]" clause, you need to post what isContainer does.

Storyboard Segue with popup button and detailview

I am creating a news app that has title, description, video and details.
this is displayed on UIViewCell on TableView, when a user clicks on that
particular cell, corresponding news is displayed as shown below
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NewsViewController *newsdetail = [[NewsViewController alloc] initWithNibName:#"NewsDetailView" bundle:nil];
self.newsdetails = detail;
[detail release];
newsdetails.title = [NSString stringWithFormat:#"%#",[titleData objectAtIndex:indexPath.row]];
newsdetails.itemID = [NSString stringWithFormat:#"%#",[NewsIds objectAtIndex:indexPath.row]];
[self.navigationController pushViewController:newsdetails animated:YES];
}
The variables (which hold JSON data) are properly defined in NewsViewController and synthesised as follows
NSMutableArray *NewsIds;
NSMutableArray *titleData;
NSMutableArray *descriptionData; etc
Now, what I want is to add a video button as shown on the storyboard, so that a user can click it and be able to see details of corresponding video through modal /popup
any suggestions or help?
In the Storyboard, just use an Action segue on the UIButton and select modal. Control Drag from the button to the Video Details VC. Give that segue a name, let's say
playVideo
Then inside the prepareForSegue method in your PlayersViewController.m you just add this:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"playVideo"]) {
// set properties on your destinationVieController to pass the data you need
}
}
Also use unwind segues on the buttons 'Cancel' and 'Done' in your destination VC to return to the previous TVC. Alternatively you could also use dismissViewControllerAnimated: that will be passed to the calling VC.
you should have a custom table view cell which will be handling actions and data on cell.

performSegueWithIdentifier on didSelectRowAtIndexPath

With this code every time user click on any cell will perform the segue again and again , I am wondering how could I keep track of the loaded view to keep data when switching views and not an infinite new viewcontroler.
Thanks -
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 0) {
[self.navigationController
performSegueWithIdentifier:#"rep" sender:self];
} else if (indexPath.row == 1) {
[self.navigationController
performSegueWithIdentifier:#"rep1" sender:self];
}
}
Try my other approach first, but if you really need a maintain a pointer to the new view controller you could try this approach. This should perform the segue once, creating the reference to the view controller which will subsequently be manually pushed into the navigation controller.
Override the view controller methods:
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender{
if(self.myViewController == nil){
return YES;
}else{
[self.navigationController pushViewController:self.myViewController animated:YES]
}
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
self.myViewController = (MyViewController*)segue.destinationViewController;
self.myViewController.customVar = 1; //perform initial customization
}
What do I know though, I've never used Storyboards...
Perhaps an alternative to maintaining a reference to the view controller would be to customize the view controller prior to seque.
Override the view controller method:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
MyViewController *targetController = (MyViewController*)segue.destinationViewController;
targetController.customVar = 1;
}
The default implementation of this method does nothing. Your view controller overrides this method when it needs to pass relevant data to the new view controller. The segue object describes the transition and includes references to both view controllers involved in the segue.
You don't need to take new View controller each and every time for each row unless and until you want it customized. This will make large amount of view controllers on storyboard.
So, Just command drag segue from controller A to B. Example: if A is tableViewController and B is simple VC where you are displaying data of table's row then command drag from whole tableViewController to B. Now this will act as common segue with one identifier only.
So in your code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//Set your B's label/property etc to cell's data or anything so that it will reflect in B.
B.label = cell.text;
[self performSegueWithIdentifier:#"Identifier" sender:self];
}
Hope this helps.
I think you can keep the new viewController's pointer. Then next time you can use it like this:
[self.navigationController pushViewController:thePointer animated:YES]
I very seldom use Storyboard. So I am not sure it will work.

prepareForSegue called before didSelectRowAtIndexPath only when third segue is added

I have 3 segues to 3 different views. 2 are implemented with no problem, it is when the third is created that the problems occur.
I have the following didSelectRowAtIndexPath method:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSLog(#" ---------- did select row");
if(indexPath.section == 0){
if(indexPath.row == [self.data count]-1){
//prior to adding this, everything works
[self performSegueWithIdentifier:#"MoreComments" sender:self];
}else{
[self performSegueWithIdentifier:#"FriendView" sender:friend];
}
}else if(indexPath.section == 1){
if(indexPath.row == [self.data2 count]-1){
[self performSegueWithIdentifier:#"MorePosts" sender:self];
}else{
[self performSegueWithIdentifier:#"FriendView" sender:friend];
}
}
}
I have the following prepareForSeque method:
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:#"MorePosts"]){
MorePostsViewController *mfamvc = segue.destinationViewController;
mfamvc.data = self.data;
}else if([segue.identifier isEqualToString:#"FriendView"]){
FriendViewController *fvc = segue.destinationViewController;
fvc.friend = friend;
}else if([segue.identifier isEqualToString:#"MoreComments"]){
MoreCommentsViewController *mcvc = segue.destinationViewController;
mcvc.data = self.data2;
}
}
Before control dragging from my cell to the last view I can see that my program hits didselectrow and then prepareforseque. This makes all the view navigation work perfect.
As soon as I control drag from my cell to the MoreCommentsViewController I start to see the error:
nested push animation can result in corrupted navigation bar
Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted.
I notice that now also prepareforseque is being called twice, with prepareforseque being called first, then didselectrow, then prepareforsegue again.
What am I doing wrong to conditionally go to these different views?
You should use either didSelectRowAtIndexPath or segues from cell, but not both. If you want your didSelectRowAtIndexPath to invoke segues, those segues should not be from the cell to the next scene, but rather from the view controller icon in the bar above the scene:
You can now select this new segue, go to the "attributes inspector" (option+command+4), and supply a storyboard identifier which you can reference in your code when you call performSegueWithIdentifier.
The reason is you can't drag from a tableview cell to multiple views. As #rdelmar mentioned this is wrong. You should drag from the destination to the source view and then handle manually the way I did above.
Also can be found here: Conditional segue performed on tap on UITableViewCell

sending some data via prepareForSegue issue

I have some issue when doing the segue with some data to to another view.
I have a contact book, first tableview is displaying contacts correctly, also with images
While I click on contact it should perform segue to another tableView. But from some reason it takes only first contact (seems like it's not in a loop).
I have one class for contacts and second ViewController. I can't understand why it happens
I created "pastie" link:
Here is the link to My code, to save place
I checked your code and I think that the problem is when the prepareForSegue is called the selected row is already deselected from didSelectRowAtIndexPath. I think that the best approach here is to send the selected index path from didSelectRowAtIndexPath into performSegue method something like:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self.contTableView deselectRowAtIndexPath:indexPath animated:YES];
[self performSegueWithIdentifier:#"NextTable" sender:indexPath];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"NextTable"]) {
NSIndexPath *indexPath = (NSIndexPath*)sender
contact = self.contactsToShow[indexPath.row];
[segue.destinationViewController setPhoneNumbers:contact.numbers];
}
}
In order for this approach to work you must link the segue between view controllers not between cell and table view controller.
The Problem is line 196: You wanna have the index path for the selected row. But because in line 215 you are deselecting the cell immediately after being selected, the index path is always 0.

Resources