Navigation Bar subview tree might get corrupted issue - objective-c

i am trying to send the view to next view but when i try to come back to the root page it crashes and say that Navigation Bar subview tree might get corrupted issue
- (IBAction)nxtBtn:(id)sender {
//here i am sending it to next view...
[self performSegueWithIdentifier:#"next" sender:(id)sender];
}
//function for segue
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
//next is the name of the identifier
if ([segue.identifier isEqualToString:#"next"]) {
nextViewController *vc=(nextViewController *)segue.destinationViewController;
vc.str=sender;
}
}

we don't need any kind of identifier for simple use of segue i.e. navigating from one view to another without passing any data. just simple as that you have to connect the segue from one view to other and run the application. it will work properly.

Related

error while loading xib file from tableview in ios

i am trying to make an app in which i use tableview.
I am populating the tableview and i am able to display data in the table. Now what i am trying to do is when i click a specific cell in the tableview i want to load a particular xib file in different folder. For all other cell i want to load second tableview. i am using a storyboard.
i am using
(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([((UITableViewCell *)sender).textLabel.text isEqualToString:#"ABCD"]) {
ABCD *abcdViewController = [[ABCD alloc] initWithNibName:#"ABCD" bundle:nil];
// Push the view controller.
[self.navigationController pushViewController:ABCDViewController animated:YES];
}
// Pass the selected object to the new view controller.
NSLog(#"%#", ((UITableViewCell *)sender).textLabel.text);
MethodsViewController *methodsViewController = segue.destinationViewController;
NSString *rowTitle = ((UITableViewCell *)sender).textLabel.text;
NSDictionary *selected = [[self methodsDict] objectForKey:rowTitle];
methodsViewController.rows = [selected objectForKey:#"rows"];
methodsViewController.methodsDict = [selected objectForKey:#"methodsDict"];
}
This is the code i am using. i made this code after searching the internet.
but the problem is
but when i build and run this the first tableview is shown and when i click on the ABCD cell the xib loads but the navigation bar is covering the upper portion of the xib file and when i click on the back button in the navigation bar it takes me to the black blank page and shows a 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.
and the app stops
I dont know what i am doing wrong i am new to ios
I hope you understand my problem
Thanks in advance
You have at least three possible approaches to what you are trying to do.
The easiest one is using shouldPerformSegueWithIdentifier: to control exactly when segueing as specified in IB and when pushing your ABCD view controller instead:
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender{
if ([((UITableViewCell *)sender).textLabel.text isEqualToString:#"ABCD"]) {
ABCD *abcdViewController = [[ABCD alloc] initWithNibName:#"ABCD" bundle:nil];
// Push the view controller.
[self.navigationController pushViewController:ABCDViewController animated:YES];
return NO;
}
return YES;
}
This should work pretty easily for you, since it is similar to what you have been trying to do with prepareForSegue:. The fault with your current approach using prepareForSegue: is that you are both pushing your ABCD controller and doing the segue. shouldPerformSegueWithIdentifier: allows you to cancel the segue, so to say, when you are going to push manually.
Another approach would be using manual segues:
you can create a manual segue in IB by dragging from the view controller (as opposed to dragging from the prototype table cell); you can create multiple named segues;
in your table view delegate you override tableView:didSelectRowAtIndexPath: so that it calls performSegueWithIdentifier::
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *identifierOfSegueToCall;
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:nowIndex];
if ([cell.textLabel.text isEqualToString:#"ABCD"]) {
identifierOfSegueToCall = #"ABCDSegueIdentifier";
} else {
identifierOfSegueToCall = #"XYWZCellSegueIdentifier";
}
[self performSegueWithIdentifier:identifierOfSegueToCall sender:self];
}
Finally, a third approach would be defining two different cell prototypes for your table view and segueing from each prototype cell into the appropriate view controller. This is similar to what you have already done for setting up your current segue, only you should add a new prototype cell and define a specific segue from it.

Object becomes Nil when pushing controller

I have a the first application controller, MAViewControllerMenu, and when that controller loads, I already allocate the next controller, imageControllerView.
- (void)viewDidAppear{
[super viewDidAppear:(YES)];
if (!imageControllerView)
imageControllerView = [[self storyboard] instantiateViewControllerWithIdentifier:#"chosenImageController"];
}
Then, I select an image from the image picker, and want to move to the next controller,imageControllerView, where the image would be displayed. I set the next window's image property as follows:
imageControllerView.image = [[self.pageViews objectAtIndex:(centered_image_ind)] image];
This line works, I checked that there's a value in imageControllerView.image.
However, when I move to the next controller,imageControllerView , I notice that the memory address of imageControllerView changes, or in other words, imageControllerView's properties that I change before moving to that controller, specifically image, reset when I move there.
Instead of throwing code here, I was hoping you could let me know what I should provide.
I think it's a common problem people know of:
Controller's objects re-init'ing when moving from one controller to another.
Here's a screen shot that might give a hint of what Im trying to do
Left most one is where I select pictures which in turn go into the slide show scrollview. Then I click next, and the image is supposed to appear in the centered ImageView
Thanks
OK...
You cannot "already allocate the next view controller" this won't work. There is no point in creating it like this at all. You can delete the imageViewController property (or iVar) completely.
The arrows that you have between the view controllers in your storyboard are segues. In Interface Builder you can select a segue and give it an identifier. For instance you would use something like #"ImageViewSegue".
I guess the segue is attached to the Next button. This is fine.
Now, in your MAViewControllerMenu you need to put this method...
- (void)prepareForSegue:(UIStoryBoardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"ImageViewSegue"]) {
// the controller is CREATED by the segue.
// the one you create in view did load is never used
ImageViewController *controller = segue.destinationController;
controller.image = [[self.pageViews objectAtIndex:(centered_image_ind)] image];
}
}
Now for the segues in the other direction...
You appear to be using segues to dismiss the modal views. You can't do this. What it will do is create a new view controller and present that instead of dismissing the presented view.
i.e. you'll go...
A -> B -> C -> B -> A -> B
// you'll now have 6 view controllers in memory
// each segue will create a fresh view controller with no values set.
What you want is...
A -> B -> C
A -> B
A
// now you only have one view controller because the others were dismissed.
// when you dismiss a view controller it will go back to the original one.
// the original one will have all the values you set previously.
To do this you need to create a method something like...
- (IBAction)dismissView
{
[self dismissViewControllerAnimated:YES completion:nil];
}
Then whatever the button is for your dismiss action attach it to this method.
Now delete all the backwards curly segues.
Passing info back
To pass info back to the original view controller you need a delegation pattern or something similar.
You can read more about creating a delegate at This random Google Search
Create a delegate method something like...
- (void)imageViewSelectedImage:(UIImage *)image;
or something like this.
Now when you do prepareForSegue you can do...
controller.delegate = self;
and have a method...
- (void)imageViewSelectedImage:(UIImage *)image
{
// save the method that has been sent back into an array or something
}
I might be wrong, but seems you go to your second view controller using a segue, it is normal your controller instance isn't the same than the one retrieved by [[self storyboard] instantiateViewControllerWithIdentifier:#"chosenImageController"]
you should take a look at - (void) prepareForSegue:(UIStoryboardSegue *)segue
(UIViewController method)
inside this method set your image property to the segue destination controller (check the identifier of the segue)

How to Properly Switch Between Views

I'm making an iOS app (first actual app that isn't Hello World), and it will have 2 screens. I asked on here before how to make one screen (or View Controller) open another, and this is what I figured out to use:
[self presentViewController:[[self storyboard] instantiateViewControllerWithIdentifier:#"statView"] animated:YES completion:nil];
It works. However, it gives me the following message when this runs:
Unknown class statView in Interface Builder file.
(Note: this doesn't stop me from using the app, it just seems to be a warning.
This leads me to believe I'm doing something wrong. Also, it seems I'm instantiating this new view controller, but never getting rid of it. So when I go back and forth, I imagine I might be leaving these View Controllers instantiated as new every time?
So my question is:
If there is a better way to switch between these windows, how can it be done?
If this is correct, why the error message?
The most easy way is unsing the Storyboard.
Add a button and link it to the second view.
You can use a Segue to parse data:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([[segue identifier] isEqualToString:#"SEGUENAME"]) {
SecondViewController *secondViewController = [segue destinationViewController];
secondViewController.parameter = parameter; // Parse a value
}
}

How do I call a function when a segue is exited?

Currently, my app goes from view A to view B through a segue and performs some functions in prepareForSegue. What should I do if I want to call a function that is executed when view B goes to view A (after pressing the back button on the Navigation Controller)?
I imagine that I could map the "back button" to an IBAction, but I'm not sure how I would do that, since the back button is part of the Navigation Controller and isn't directly visible on the Storyboard.
In particular, view B updates some values that view A has displayed. I want to call viewDidLoad so that view A has the updated data before it loads.
In ViewA's view controller:
// update view when it becomes visible
- (void)viewDidAppear:(BOOL)animated {
[self viewDidLoad];
}
Ah, this isn't a segue as such. This is equivalent to popViewController.
If you want to update the view when view A becomes visible then you can do that in the function...
- (void)viewWillAppear:(BOOL)animated
or in the function
- (void)viewDidAppear:(BOOL)animated
These will run each time the view becomes visible.
In here you can run your "updateView" method or whatever method you want.
If you want to pass data back to view A (i.e. view B is a "select city" view or something) then you show make view A a delegate of view B. That way you can pass the info back when the user does something.
Instead of running viewDidLoad do this...
- (void)viewDidLoad
{
[self.button setTitle:#"blah"];
[self updateView];
}
- (void)viewDidAppear:(BOOL)animated
{
[self updateView];
}
- (void)updateView
{
// do something that you want to happen
}
You shouldn't actually have to do this though. It is enough just to run [self updateView] from viewDidAppear.
You can't run viewDidLoad directly though.
In view controller "A" you need to implement the method prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender and inside create a segues destinationViewcontroller, heres a example:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:SEGUE_FOR_OPTIONS])
{
// Get reference to the destination view controller
OptionsViewController *optionVC = [segue destinationViewController];
[optionVC someMethod];
}
}

UISearchBar and segues

Im using UITableViewController to manage data. When I click on the cell my program goes to another scene (let it be myDetailViewController). But i just added search bar (UISearchViewController) and search works great but when I click on the cell from the table with the filtered data nothing happens. But I need the program to go to myDetailViewController scene to view object details. How can i perform it?
Btw, for changing views (from a basic cells, not filtered) I'm using segues. And I'm also using this method:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"nameofmysegue"]) {
//some code to give some data to new controller;
}
}
And when I'm using
tableView:didSelectRowAtIndexPath:
without segues nothing happens at all.
Make sure to connect the segue to the view controller itself and not the tableview row. Then in your didSelectRowAtIndexPath, you do a [self performSegueWithIdentifier#"mySegueID"];