Shift to Parent View Controller from child view controller - iOS - ios

I have a main Actions View Controller, and on that there is button "Review". Review Button's functionality is :
- (IBAction)btnReview:(id)sender
{
ReviewViewController *vc = [[ReviewViewController alloc]initWithNibName:#"ReviewViewController" bundle:nil];
[self addChildViewController:vc];
[vc didMoveToParentViewController:self];
[self.view addSubview:vc.view];
}
Now on Review Page, I have a button. And on that button's action, I want to switch back to Parent View Controller. Its view should be displayed. I have tried following code, it either pauses or crashes application.
[self didMoveToParentViewController:nil];
[self.view removeFromSuperview];
[self removeFromParentViewController];
I even tried:
[self dismissModalViewControllerAnimated:YES]
I have read other posts related to this question as well but could not find a satisfactory answer. Please Help!

I'm assuming that this is a custom viewcontroller container you're trying to build, "self" is the Main Actions viewController you're talking about.
Try this:
- (IBAction)btnReview:(id)sender
{
ReviewViewController *vc = [[ReviewViewController alloc]initWithNibName:#"ReviewViewController" bundle:nil];
[self addChildViewController:vc];
[self.view addSubview:vc.view];
[vc didMoveToParentViewController:self];
vc = nil;
}
For the "Back" button, I'm assuming this is the Button to return to Main Actions viewController from the Review viewController, try this:
- (IBAction)btnReviewHide:(id)sender
{
[self willMoveToParentViewController:nil];
[self.view removeFromSuperview];
[self removeFromParentViewController];
}
Hope this helps.

You should use delegation. When you click the button in your ReviewViewController, you call a method like: [self.delegate hideReviewController:self];
And this method would look something like:
- (void)hideReviewController:(ReviewViewController *)controller {
[UIView animateWithDuration:0.3
delay:0
options:UIViewAnimationOptionCurveEaseInOut
animations:^{
controller.view.alpha = 0;
} completion:^(BOOL finished) {
[self.view removeSubview:controller.view];
// If you want the Review Controller to be deallocated:
[self removeChildViewController:controller];
}];
}
EDIT:
In your ReviewDelegate.h file add:
#class ReviewViewController;
#protocol ReviewDelegate <NSObject>
- (void)hideReviewController:(ReviewViewController *)controller;
#end
Then add this property:
#property (nonatomic, weak) id <ReviewDelegate> delegate;
In the parent class:
- (IBAction)btnReview:(id)sender
{
ReviewViewController *vc = [[ReviewViewController alloc]initWithNibName:#"ReviewViewController" bundle:nil];
vc.delegate = self;
[self addChildViewController:vc];
[vc didMoveToParentViewController:self];
[self.view addSubview:vc.view];
}
- (void)hideReviewController:(ReviewViewController *)controller {
[UIView animateWithDuration:0.3
delay:0
options:UIViewAnimationOptionCurveEaseInOut
animations:^{
controller.view.alpha = 0;
} completion:^(BOOL finished) {
[self.view removeSubview:controller.view];
// If you want the Review Controller to be deallocated:
[self removeChildViewController:controller];
}];
}
I also suggest that you read about delegation

Try this
self.view=nil;
[self willMoveToParentViewController:nil];
[self.view removeFromSuperview];
[self removeFromParentViewController];

You don't need to make it complex... Just use UINavigationController.
To navigate from ParentVC to ChildVC :
ChildViewController *ChildVC = [[ChildViewController alloc]initWithNibName:#"ChildViewController" bundle:nil];
[self.navigationController pushViewController:ChildVC animated:YES];
And for navigating back from ChildVC to ParentVC :
ParentViewController *ParentVC = [[ParentViewController alloc]initWithNibName:#"ParentViewController" bundle:nil];
[self.navigationController popViewControllerAnimated:YES];

Since you are adding the Child View as a Subview on to Parent you need to manually it from its superview (in your case parentview). Rather then adding it as a subview you can make use of presentViewController method as follow:
- (IBAction)btnReview:(id)sender
{
ReviewViewController *vc = [[ReviewViewController alloc] initWithNibName:#"ReviewViewController" bundle:nil];
[self presentViewController:vc
animated:YES
completion:nil];
}
and in the child class code for back button will be :
-(IBAction)backButtonClicked:(id)sender
{
[self dismissViewControllerAnimated:YES completion:nil];
}

Sounds like what you're looking for could be taken care of with a UINavigationController. Just use pushViewController: to push the new view onto the screen. Then, a back button will appear in the navigation bar atop the view, which can be used to return to the "parent" view controller.
See the documentation.

writing only
- (IBAction)backbutton:(id)sender {
[self.navigationController popToRootViewControllerAnimated:YES];
}
worked in my case

Related

Swap views in a container view

I'd like to swap two custom UIViewControllers inside a ContainerView. To do this I created a ViewController that handles the logic of the swapping. This swap should occur when pressing a button.
What I want to do is similar to this. I tried the current accepted answer but the problem is that the layout doesn't show up. I don't get any compile errors or warnings.
I have this code in the ContainerViewController, executed when the button is pressed.
if([view isEqualToString:#"view1"]){
NSString *userId = [self getUserId];
ViewController1 *vc = [[ViewController1 alloc]init];
[vc someFunction:userId];
UIViewController *fromViewController = [self.childViewControllers firstObject];
[self swapViewController: fromViewController toViewController:vc];
}else{
NSString *userId = [self getUserId];
ViewController2 *vc = [[ViewController2 alloc]init];
[vc otherFunction:userId];
UIViewController *fromViewController = [self.childViewControllers firstObject];
[self swapViewController: fromViewController toViewController:vc];
}
The swapViewController function looks like this:
- (void)swapViewController:(UIViewController *)fromViewController toViewController:(UIViewController *)toViewController
{
toViewController.view.frame = fromViewController.view.frame;
[fromViewController willMoveToParentViewController:nil];
[self addChildViewController:toViewController];
[self transitionFromViewController:fromViewController
toViewController:toViewController
duration:0.5
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
}
completion:^(BOOL finished) {
[fromViewController removeFromParentViewController];
[toViewController didMoveToParentViewController:self];
}];
}
This is what I have in the storyboard:
If I just simply load the segue it works fine, but I need to show some data received over the internet, so I think it's not an option.
Could anyone please, give me directions on how to achieve that?

Navigation Bar hiding when moving to new view controller

When I am trying to move from one view controller to other by pressing on a table view cell in the present view controller. The problem is when I do this :
FGTipViewController *vc = [[FGTipViewController alloc] initWithNibName:#"FGTipViewController" bundle:nil];
[self.navigationController pushViewController:vc animated:YES];
It takes me to the new view controller but the navigation bar disappears. This happens for a particular view controller only and works fine for others. I am not able to make out any elementary difference between these classes. What could be the cause of this kind of problem? Let me know if more details are required.
Try these lines when you push your view,
FGTipViewController *vc = [[FGTipViewController alloc] initWithNibName:#"FGTipViewController" bundle:nil];
[self.navigationController pushViewController:vc animated:YES];
[self.navigationController setNavigationBarHidden:NO animated:YES];
And also in the viewWillAppear method of FPTipViewController,
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.navigationController setNavigationBarHidden:NO animated:YES];
}
In FGTipViewController,
-(void) viewWillAppear:(BOOL) animated {
[super viewWillAppear];
[[self navigationController] setNavigationBarHidden:NO animated:YES];
}
I did this and it works. Thanks!
UINavigationBar* navBar = self.navigationController.navigationBar;
if (navBar) {
[UIView animateWithDuration:ANIMATION_DURATION animations:^{
[navBar setFrame:CGRectMake(0, 20, navBar.frame.size.width, navBar.frame.size.height)];
}];
}

Message sent to deallocated instance - view as property

In my app, you click a button which reveals another page. Whenever you click a button on the view it crashes and shows this:
IBAction on the button:
- (IBAction)searchOptions:(id)sender {
FilterViewController *ctrl = [[FilterViewController alloc] init];
[UIView transitionFromView:self.view toView:ctrl.view duration:1 options:UIViewAnimationOptionTransitionCurlUp completion:nil];
[self.navigationController pushViewController:ctrl animated:NO];
}
In the .h file I have a forward class declaration and set the property:
#import "FilterViewController.h"
#class FilterViewController;
#property (strong) FilterViewController *filterViewController;
I am unsure what is going on here!
Assuming you are using ARC, your ctrl instance is never kept so it is released and deallocated. You need to keep a strong reference to the object.
Perhaps assigning ctrl to the filterViewController property is was you meant to do.
- (IBAction)searchOptions:(id)sender {
FilterViewController *ctrl = [[FilterViewController alloc] init];
[UIView transitionFromView:self.view toView:ctrl.view duration:1 options:UIViewAnimationOptionTransitionCurlUp completion:nil];
self.filterViewController = ctrl;
[self.navigationController pushViewController:ctrl animated:NO];
}
Update:
Never mind. I totally missed the last line where you push ctrl onto the nab controller. Given this, my initial answer isn't correct at all.
In your - (IBAction)searchOptions:(id)sender do this instead
- (IBAction)searchOptions:(id)sender {
self.filterViewController = [[FilterViewController alloc] init];
[UIView transitionFromView:self.view self.filterViewController.view duration:1 options:UIViewAnimationOptionTransitionCurlUp completion:nil];
[self.navigationController pushViewController:self.filterViewController animated:NO];
}

iOS UIViewAnimation not working

I have a master detail application that when the detail view appears and a string is empty, I want it to present a new view through a UIViewAnimationFlip. The animation is working, but it keeps flipping to itself, not the view controller I initiated. Any help would be great!
- (void)viewDidAppear:(BOOL)animated {
if (masterView.parserURL == nil) {
LoginViewController *login = [[LoginViewController alloc] init];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.8];
[UIView setAnimationTransition:UIModalTransitionStyleFlipHorizontal
forView:self.view
cache:YES];
[self.navigationController presentViewController:login
animated:YES
completion:nil];
[UIView commitAnimations];
}
}
I agree that you should be doing this modally, instead of just adding a subview. In your example code you are animating twice, because the presentviewcontroller method is animating itself already. Try removing the other animation code as follows:
LoginViewController *login = [[LoginViewController alloc] init];
login.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:login
animated:YES
completion:nil];
I'm suggesting simply:
- (void)viewDidAppear:(BOOL)animated {
if (masterView.parserURL == nil) {
LoginViewController *login = [[LoginViewController alloc] init];
login.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:login
animated:YES
completion:nil];
}
}
Note, there's an interesting question of how the login screen is supposed to update that parserURL field in masterView. You might add a property to your login controller that is a pointer to masterView, so that it has a mechanism to update the parserURL. Thus it might be like:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
if (masterView.parserURL == nil)
{
LoginViewController *login = [[LoginViewController alloc] init];
login.masterView = masterView;
login.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:login
animated:YES
completion:nil];
}
}
Then your login controller can now update the parserURL via:
self.masterView.parserURL = ... // set it as appropriate

push uiviewcontroller from presentModalViewController

I Show a view using presentModalViewController. and from this UIView I want to push a UIView using UINavigationController.
I tried below code for this
[self.parentViewController.navigationController
pushViewController:objViewFullScreen
animated:YES];
But it did not works for me. so please can any one suggest how I push a view from ModelViewController.
Thanks
First you have to present your modal view controller inside a navigation controller:
MyViewController *vc = [[MyViewController alloc] initWithNibName:#"MyNib" bundle:nil];
UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:vc];
[self presentModalViewController:nc animated:YES];
[vc release];
[nc release];
Then inside MyViewController you can do:
OtherViewController *vc = [[OtherViewController alloc] initWithNibName:#"MyOtherNib" bundle:nil];
[self.navigationController pushViewController:vc animated:YES];
[vc release];
-(void)pushViewControllerWithCustomAnimation:(UIViewController *)newViewController {
newViewController.view.alpha = 0.0f;
[self.view addSubview:newViewController.view];
[UIView animateWithDuration:1
animations:^{
newViewController.view.alpha = 1;
}
completion:^(BOOL fin){
if (fin) {
// finally display the new viewcontroller for real
[self.navigationController pushViewController:newViewController animated:NO];
}
}];
}

Resources