setView with ChildViewController - ios

I have ViewController with child, it's works great, but when I change root view to another, and then return back the root view:
-(void)showSearchResultView
{
self.searchView.frame = self.view.frame;
__rootView = self.view;
[self setView:self.searchView];
}
-(void)hideSearchResultView
{
if(__rootView) [self setView:__rootView];
__rootView = nil;
}
I'm getting the exception:
Terminating app due to uncaught exception 'UIViewControllerHierarchyInconsistency',
reason: 'child view controller:<SlideViewController> should have parent view controller:
<UINavigationController> but actual parent is:<MainViewController>'
What is the proper way to change root view with child view controllers?

For changing root view you have to remove rootviewcontroller from navigation stack.
Like :
NSMutablerray *controllers = [self.navigationController viewcontrollers];
[controllers removeObjectAtIndex:0];
it will remove the rootviewController and name way you can add new view Controllers.
[controllers addObjectAtIndex:0];
Note:- This code syntax might be incorrect .this is just a approach.
Update:-
NSMutableArray *viewControllers = [[NSMutableArray alloc]initWithArray:self.navigationController.viewControllers];
RootViewController *root = [[RootViewController alloc]initWithNibName:#"RootViewController" bundle:nil];
[viewControllers insertObject:root atIndex:0];
self.navigationController.viewControllers = viewControllers;
This way you can change your root view.

I found the solution. Just remove the children root views and add it again.
-(void)showSearchResultView
{
self.searchView.frame = self.view.frame;
__rootView = self.view;
[self setView:self.searchView];
for(UIViewController* vc in self.childViewControllers){
[vc.view removeFromSuperview];
}
}
-(void)hideSearchResultView
{
if(__rootView) [self setView:__rootView];
__rootView = nil;
for(UIViewController* vc in self.childViewControllers){
vc.view.frame = self.view.bounds;
[self.view addSubview:vc.view];
}
}

Related

how to remove child class from parent when I get sucess message in the childview controller

I am presenting viewcontroller as chid viewcontroller.I Am presenting child viewcontroller in a popupview which is in parent class.plase find the below image to get clear idea.
This the code i used to add present childvc in parent.
[self.view addSubview:yopopup_view];
yopopup_view.hidden=NO;
yoviewcontroller = [storyBoard instantiateViewControllerWithIdentifier:#"yoviewcontroller"];
CGRect contentFrame = yocontantview.frame;
contentFrame.origin.y = yocontantview.frame.origin.y;
contentFrame.size.height = yocontantview.frame.size.height;
yocontantview.frame = contentFrame;
yoviewcontroller.view.frame = yocontantview.bounds;
[yocontantview addSubview:yoviewcontroller.view];
[self addChildViewController:yoviewcontroller];
[yoviewcontroller didMoveToParentViewController:self];
Now i the childvc I have an api class when I get success message from backend I have remove child class from parentvc.
I am using the below code to remove child class from parent class.
[self willMoveToParentViewController:nil];
[self.view removeFromSuperview];
[_delegate closeyopopmethod:#"close"];
[self removeFromParentViewController];
When I use the code I am removing the child class but I have to remove popupview from the parent class superview.How to do that.
Thanks for quick responce.
You haven't set the delegate of yoviewcontroller, so set it to self when you initialized it.
yoviewcontroller = [storyBoard instantiateViewControllerWithIdentifier:#"yoviewcontroller"];
//Set the delegate to self
yoviewcontroller.delegate = self;
//Your other code
UIViewController *vc = [self.childViewControllers lastObject];
[vc.view removeFromSuperview];
[vc removeFromParentViewController];

Double UINavigationBar in UITabBarController

We have a UINavigationViewController as root viewController in AppDelegate:
Restore *callRestore=[[Restore alloc]initWithNibName:#"Restore" bundle:nil];
self.navigationController = [[UINavigationController alloc] initWithRootViewController:callRestore];
self.window.rootViewController = self.navigationController;
We are pushing a new viewController (TabViewController) from above Restore:
callTabView=[[TabViewController alloc] initWithNibName:#"TabViewController" bundle:nil];
[self.navigationController pushViewController:callTabView animated:YES];
In this TabViewController we are adding UITabBarController programatically as subview and in this UITabBarController we have 5 UINavigationBarController as view controllers:
NSArray* controllers = [NSArray arrayWithObjects:navControllerDashboard, navControllerAccounts, navControllerTransation,navControllerCallDisplayReports,navControllerMore, nil];
self.tabBarController.viewControllers = controllers;
self.tabBarController.delegate = self;
self.tabBarController.view.frame = self.view.frame;
[self.view addSubview:self.tabBarController.view];
When we are rotating any view from these 5 UINavigationViewController we are getting 2 UINavigationBar on top in both landscape and portrait mode.
Check below image.
and didRotateFromInterfaceOrientation is not calling from these 5 UINavigationViewController view.
Any help?
When you add a view controller to another one as a subview manually you have to do the following:
UIViewController *parent = ...;
UIViewController *child = ...;
[child willMoveToParentViewController: parent];
[parent addChildViewController: child];
[parent.view addSubview: child.view];
[child didMoveToParentViewController:parent];
This will propagate all the events to the child view controller and possibly remove unexpected behaviour.

Correct adding and UIViewController to another

Tonight one faced with this:
- (void)loadView {
VC *vc = [[VC alloc] initWithStyle:UITableViewStyleGrouped];
[self addChildViewController:vc];
[vc removeFromParentViewController];
[self setView:vc.view];
}
and got a bomb:
uncaught exception 'UIViewControllerHierarchyInconsistency', reason:
'A view can only be associated with at most one view controller at a time!
Q: How we can directly add vc and all its functionality to current ViewController without AddSubView?
Add your table view controller's view as a subview of the current view. You shouldn't call removeFromParentViewController on vc because that would essentially negate the line before. It's also a good idea to set the frame to match the parent.
- (void)loadView
{
[super loadView]; // this will create a basic view
VC *vc = [[VC alloc] initWithStyle:UITableViewStyleGrouped];
[self addChildViewController:vc];
vc.view.frame = self.view.bounds;
vc.view.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
[self.view addSubview:vc.view];
[vc didMoveToParentViewController:self];
}

UisplitViewController issue in ios 7(crash)

I have to instantiate in one of the view controllers.
UISplitViewController *splitViewController = [kStoryBoard instantiateViewControllerWithIdentifier:#"splitController"];
UINavigationController *navigationController = [splitViewController.viewControllers lastObject];
splitViewController.delegate = (id)navigationController.topViewController;
splitViewController.navigationController.navigationBarHidden = YES;
splitViewController.presentsWithGesture = NO;
UISwipeGestureRecognizer *swipeRecognizer = [[UISwipeGestureRecognizer alloc]initWithTarget:navigationController.topViewController action:#selector(swipeDetected:)];
swipeRecognizer.direction = UISwipeGestureRecognizerDirectionLeft|UISwipeGestureRecognizerDirectionRight;
[splitViewController.view addGestureRecognizer:swipeRecognizer];
CGRect frame = splitViewController.view.frame;
frame.origin.x = 0;
frame.size.height -=100;
frame.origin.y +=100;
splitViewController.view.frame = frame;
UINavigationController *masterNavigationController = [splitViewController.viewControllers objectAtIndex:0];
MasterViewController *masterVC = (MasterViewController*)[masterNavigationController topViewController];
masterVC.currentCategory = [categoriesArray objectAtIndex:sender.tag-1];
self.navigationController.navigationBarHidden = YES;
[self.navigationController setViewControllers:[NSArray arrayWithObject:splitViewController] animated:YES];
My app crashes on this line.
[self.navigationController setViewControllers:[NSArray arrayWithObject:splitViewController] animated:YES];
It is working fine for ios 5 and ios 6.
Crash occurs only in ios 7.
This is the error.
[UINavigationController _setViewControllers:transition:animated:], /SourceCache/UIKit/UIKit-2903.2/UINavigationController.m:768
2013-10-21 18:51:37.009 TruAirSync[1723:60b] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UISplitViewControllers are not allowed in a navigation controller!'
Found the answer.
Hope it will help others also.
We just need to use a view controller.
UIViewController *containerVC = [[UIViewController alloc]init];
[containerVC.view setFrame:splitViewController.view.frame];
[containerVC.view addSubview:splitViewController.view];
[containerVC addChildViewController:splitViewController];
[splitViewController didMoveToParentViewController:containerVC];
[self.navigationController setViewControllers:[NSArray arrayWithObject:containerVC] animated:YES];
Just create another UIViewController and add you splitviewcontroller's view to it's subview than you can use it in a UINavigationController.
YourContainerController *containerController = [YourContainerController new];
[containerController.view addSubview:splitViewController.view];
[self.navigationController setViewControllers:#[containerController] animated:YES];
The UISplitViewController should be the root view of your application window. Not sure why this was working for you in iOS 5 and 6. You can not push a UISplitViewController into a UINavigationController.
From Apple's documentation:
A split view controller must always be the root of any interface you
create. In other words, you must always install the view from a
UISplitViewController object as the root view of your application’s
window.

Issue with definesPresentationContext / UIModalPresentationCurrentContext - Current context view controller gets lost

This only accours if you are presenting in a view controller that is managed by a navigation controller.
The reproduction steps are:
1 - Present a view controller using UIModalPresentationCurrentContext
self.definesPresentationContext = YES;
ViewController* viewController = [[ViewController alloc] init];
viewController.modalPresentationStyle = UIModalPresentationCurrentContext;
[presentOnViewController presentViewController:viewController animated:YES completion:nil];
2 - Present a view controller over the top using the default full screen presentation style
ViewController* viewController = [[ViewController alloc] init];
[self presentViewController:viewController animated:YES completion:nil];
3 - Dismiss the top presented view controller (the full screen one)
[self dismissViewControllerAnimated:YES completion:nil];
Now the problem is the 2nd view controller (presented using UIModalPresentationCurrentContext) disappears. Also it is impossible to present another view controller using UIModalPresentationCurrentContext, because the system thinks its still there.
I believe the issue is a bug in the framework. As mentioned it only occurs when the presenting in a view controller managed by a navigation controller. There is a nasty work around which uses the containment API. It creates a dummy view controller which views are presented from. The steps are:
1 - When presenting a view in context who's parent is a navigation controller, use a dummy view controller:
- (void)presentInContext
{
UIViewController* presentOnViewController = self;
if ([self.parentViewController isKindOfClass:[UINavigationController class]])
{
// Work around - Create an invisible view controller
presentOnViewController = [[DummyViewController alloc] init];
presentOnViewController.view.frame = self.view.frame;
// Containment API
[self addChildViewController:presentOnViewController];
[self.view addSubview:presentOnViewController.view];
[presentOnViewController didMoveToParentViewController:self];
presentOnViewController.definesPresentationContext = YES;
}
ViewController* viewController = [[ViewController alloc] init];
viewController.modalPresentationStyle = UIModalPresentationCurrentContext;
[presentOnViewController presentViewController:viewController animated:YES completion:nil];
}
2 - When dismissing the view controller tidy up
- (void)dismissSelf
{
__weak UIViewController* presentingViewController = self.presentingViewController;
[self dismissViewControllerAnimated:YES completion:^{
// Remove the dummy view controller
if ([presentingViewController isKindOfClass:[DummyViewController class]])
{
[presentingViewController willMoveToParentViewController:nil];
[presentingViewController.view removeFromSuperview];
[presentingViewController removeFromParentViewController];
}
}];
}
Thats it... The fix is dirty, but does the trick with no visual flicker.

Resources