presentViewController is moving my rootViewController - iphone

I would like to know if anyone have an idea about a problem I have !
I have a simple viewController, with a custom appDelegate.window.frame (0, 20, width, height), with its own navigationController. I implemented a UIButton, that present an empty view controller.
UIViewController *v = [_controllersList objectAtIndex:indexPath.row];
v.modalPresentationStyle = UIModalPresentationCurrentContext;
[self presentViewController:v animated:YES completion:nil];
By now, everything is working. If I present that new controller (everything is fine with it!). When I dismiss the new view, my original view controller frame has changed graphically but not programmatically!
(The result is that my window is stuck to the top of the view, and cropped, with 20 blacks pixel to the bottom).

For me the solution was changing the default modalPresentationStyle property:
v.modalPresentationStyle = UIModalPresentationOverFullScreen;
Hope it helps.

you can present the view controller from the window rootviewcontroller
[self.view.window.rootViewController presentViewController:v animated:YES completion:nil];

Check your Auto-Layout option. May be the issue for the auto-layout.

This solution will resolve your problem,when ever you Dismiss a view then view will appear will call every time.
-(void)viewWillAppear:(BOOL)animated {
self.view.frame = [[UIApplication sharedApplication].keyWindow bounds];
}

Related

Objective-c: presentViewController from UIView

Im trying to use presentViewController inside a UIView.
http://img145.imageshack.us/img145/6334/appt.png
When I click he "+" button at the top/right, I want to replacer the tableview at the right (in the grey part of the image) by a UIViewController.
- (void)add:(id)sender
{
UIViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"testview"];
[self presentViewController:controller animated:YES completion:NULL];
}
Of course by doing this, the whole screen is replaced..
I want something like this:
[contentView addSubview:controller];
or
[contentView presentViewController:controller animated:YES completion:NULL];
where contentView is an UIView containing the tableview
I found this addChildViewController and presentViewController but I don't think that can help me out
Thanks
EDIT:
Use ContainerView in storyboard solved my problem
You can add the controller's view as a subview of your contentView. Be sure to keep a strong reference to the controller when you do that though.
Another approach would be to make the new view owned by the presenting controller instead of a second controller and simply hide/show views as needed.
edit your statement:
[self.navigationController presentViewController:controller animated:YES completion:NULL];
try this and then let me know if it worked!
I am not sure if I understand you right. From your picture I believe you are programming for an iPad, and you want to cover the whole view partly by another view. If so, you could use a UIPopoverController, which does exactly this.
A PopoverController seems to be what you need. Here is some boilerplate code:
UIPopoverController* aPopover = [[UIPopoverController alloc]
initWithContentViewController:navigation];
self.aPopoverController = aPopover;
[self.aPopoverController presentPopoverFromRect:nil inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
aPopoverController is a property of the class.
#property UIPopoverController* aPopoverController;
If I understand clearly. This would help you out
SomeViewController *viewController=[[SomeViewController alloc]init];
[viewController setFrame:CGRectMake(x,y,width,height)];
[self.view addsubview:viewController.view];
Sorry if Iam wrong...

UIModalPresentationCurrentContext with Transition?

I am trying to modal present a view controller like below:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"addPopover"];
vc.view.backgroundColor = [UIColor clearColor];
self.modalPresentationStyle = UIModalPresentationCurrentContext;
[self presentModalViewController:vc animated:YES];
Now using UIModalPresentationCurrentContext means I can present this view with a transparent background and see my other view behind the new one. However, it stops me from being able to present it with a transition.
Any ideas why? Or how I can get around this? Thanks.
I was able to accomplish this by setting modalPresentationStyle = UIModalPresentationCurrentContext on the rootViewController of my UIWindow, IF I haven't presented any new full screen viewControllers on top of this rootViewController. I did something like this:
UIViewController *rootViewController = [UIApplication sharedApplication].delegate.window.rootViewController;
rootViewController.modalPresentationStyle = UIModalPresentationCurrentContext;
[self presentViewController:vc animated:YES completion:nil];
I've tried this with both a UINavigationController as my window's rootViewController and various other custom view controllers. It seems as long as the window's rootViewController knows what's going on, any sub-viewControllers can call presentViewController:animated:completion: without blacking-out the underlying view.
However, let's say you present another viewController on top of your window's rootViewController. And this new viewController is presented with modalPresentationStyle = UIModalPresentationFullScreen (ie. takes up the screen), then you have to call modalPresentationStyle = UIModalPresentationCurrentContext on that top-most viewController.
So to recap:
If you have UINavigationController -> UIViewController(s) (they could be pushed and popped in and out), then you set modalPresentationStyle = UIModalPresentationCurrentContext on the UINavigationController.
If you have UINavigationController -> UIViewController -> new-UIViewController (with modalPresentationStyle set to UIModalPresentationFullScreen), then you set modalPresentationStyle = UIModalPresentationCurrentContext on the new-UIViewController.
Hopefully this works for you guys as well!
Full screen modals aren't supposed to allow you to see the under layer. Annoying I know.
From your code I'm assuming that "addPopover" is actually a full screen view, where you have your content as a subsection while the rest is transparent.
Try this:
vc.modalPresentationStyle = UIModalPresentationCurrentContext;
vc.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentViewController:vc animated:YES completion:NULL];
Note: I'd recommend adding a low alpha background color to let the user know that they can't interact with the rest of the view when you pop this over top...
Mr. T's suggestions worked nearly perfectly, you just lose the transition animation on the presented viewcontroller
Since it is also setting the appDelegates rootviewController's presentation style, it will also remove the transition animations for any views presented from that point.
My fix was to return the AppDelegates rootViewController's presentation style back to it's default whenever the viewcontroller is closed that I needed the transparent background on
I have a button that dismisses the presentedViewController, in that I also set the presentation style of the rootViewController back to default using:
UIViewController *rootViewController = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
rootViewController.modalPresentationStyle = UIModalPresentationFullScreen;
I hope that helps anyone else getting stumped on this problem.

Modal View Controller Won't Start in Landscape Mode

I have a navigation based app that has a detail view (UIWebView) with action buttons across the bottom in a UIToolbar. I want to add 'notes' when the 'notes' button is pushed. Everything works fine when the webview is in portrait mode. I press the notes button, the modal view opens fine and works great.
The problem occurs when the webview is in landscape mode. If I press the notes button, all the code to open the modal view gets called but all I get is a white screen. One comment: If I open the modal view in portrait and then rotate the device, it rotates fine into landscape mode. It just won't open correctly in landscape mode.
I have another button that brings up the mail composer which has the identical behavior. Here is the code in my UIWebViewController:
- (IBAction)addNotes:(id)sender
{
NotesViewController *notesViewController;
// create the view controller and set it as the root view of a new navigation
// controller
notesViewController = [[NotesViewController alloc] initWithPrimaryKey:self.record.primaryKey];
UINavigationController *newNavigationController =
[[UINavigationController alloc] initWithRootViewController:notesViewController];
// present the navigation controller modally
[self presentModalViewController:newNavigationController animated:YES];
[notesViewController release];
[self.view setNeedsDisplay]; // not sure if I need this! I was trying different things...
[self.devotionText setNeedsDisplay]; // ditto...
[newNavigationController release];
}
Any ideas? I've tried all sorts of different things to no avail. I just get a white screen with no navigation bar (although there is a status bar at the top).
Modals don't always get information about rotations, and they get their info from the status bar, which doesn't always work right. Put this in your viewWillAppear to fix: [UIApplication sharedApplication].statusBarOrientation = self.interfaceOrientation And, if you want a navigation controller inside your modal, you need to create one.
Also, you don't need the setNeedsDisplay. That only effects the current views, not the modal you are presenting.
Answer is here:
https://stackoverflow.com/a/10250747/1449618
Use the window's root view controller to present:
[self.view.window.rootViewController presentViewController:masterView
animated:YES
completion:NULL];
Wow, I lost days over that issue ... but I found a solution!
I had the same problem you had: the method "presentModalViewController:animated:" only worked in portrait mode.
After a lot of trial and error, I found out that the reason was that I had several view controllers active at the same time. I implemented a navigation system which switched between different view controllers, with one parent handling the children. (I could not use UINavigationController, because I needed a different look.)
So, my root view controller had a root view object, and several child view controllers. When a child view controller was activated, its view object was added as subview to the view of the root view controller.
The "presentModalViewController" method didn't like that. However, as soon as I set the "parentViewController" property of the child view controllers, it worked!
The problem is only that "parentViewController" is a read-only property. You have to extend the UIViewController class so you can access it.
#interface UIViewController (HelperExtension)
#property (nonatomic, assign) UIViewController *parent;
#end
#implementation UIViewController (HelperExtension)
- (UIViewController *)parent
{
return self.parentViewController;
}
- (void)setParent:(UIViewController *)parent
{
[self setValue:parent forKey:#"_parentViewController"];
}
#end
So, whenever you add the view of a child view controller to your parent view controller, call the "setParent:" method after doing it. Then it will work!
Got the same issue when presenting modally a navigation controller. Be sure to have correctly implement : shouldAutorotateToInterfaceOrientation
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
BOOL shouldAutorotate = NO;
if( isControllerMangingAllOrientations )
{
shouldAutorotate = YES;
}
else
{
shouldAutorotate = (toInterfaceOrientation == UIInterfaceOrientationPortrait);
}
return shouldAutorotate;
}
I was setting the boolean in the viewDidLoad method, not a good idea. Putting it in the initWithNibName:bundle: method is the right place.
If you use presentModalViewController just for animation like me, you can use pushViewController with animation as below answer;
Showing pushviewcontroller animation look like presentModalViewController
and you can close the viewController as below;
CATransition* transition = [CATransition animation];
transition.duration = 0.3;
transition.type = kCATransitionFade;
transition.subtype = kCATransitionFromTop;
[self.navigationController.view.layer addAnimation:transition forKey:kCATransition];
[self.navigationController popViewControllerAnimated:NO];
Hope it helps..
I had the task to show a video player in landscape mode.
AVPlayerViewController *playerViewController = [AVPlayerViewController new];
//Player init code goes here....
// #define degreesToRadian(x) (M_PI * (x) / 180.0) - was defined previously in a class header
playerViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
playerViewController.view.transform = CGAffineTransformMakeRotation(degreesToRadian(90));
playerViewController.view.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
[self presentViewController:playerViewController animated:YES completion:nil];
You don't need a new Navigation Controller.
- (IBAction)addNotes:(id)sender {
NotesViewController *notesViewController;
// create the view controller and set it as the root view of a new navigation
// controller
notesViewController = [[NotesViewController alloc] initWithPrimaryKey:self.record.primaryKey];
[self.navigationController pushViewController: notesViewController animated: YES];
[notesViewController release];
}

Transparent Background with a Modal UIViewController

I have a dilema, I want to present to the user a semi-transparent view.
I found out by experimenting that if I simply pushed the transparent view to the top of my NavigationController's stack, that it would not render the transparency level I wanted. So I decided to simply add the view as a subview of the current view at the top of the stack.
This solution works, the view below is still visible, and the View is 'semi-modal'. The problem is, if the parent view inherits from UITableViewController (as mine does), then the view I 'push' onto it, does not cover the navigation bar at the top.
I really don't want to get into a situation where I am forced to enable / disable controls on the navigation bar every time I push this view, so I was wondering, if anyone knew of any solutions that I could use so that the view I push onto the UITableViewController will actually 'push over' the navigation bar?
Funny, I was just doing the same thing yesterday. Unfortunately it seems to be impossible. Once the modal view controller is in place, the previous view becomes hidden.
See this previous question on the topic.
You can still use the view controller and NIB files you have set up - here's my sample code
- (void)showUpgrade {
[self.upgradeVC viewWillAppear:NO];
[self.view addSubview:self.upgradeVC.view];
[self.upgradeVC viewDidAppear:NO];
}
- (void)hideUpgrade {
[self.upgradeVC viewWillDisappear:NO];
[self.upgradeVC.view removeFromSuperview];
[self.upgradeVC viewDidDisappear:NO];
}
- (UpgradeViewController *)upgradeVC {
if (_upgradeVC == nil) {
_upgradeVC = [[UpgradeViewController alloc] initWithNibName:[NSString stringWithFormat:#"UpgradeView_%#", self.deviceType] bundle:nil];
_upgradeVC.delegate = self;
}
return _upgradeVC;
}
You will need to store a reference to the parent view controller in the modal view controller so that you can access the -hide method. I did this through a delegate.
It would also be easy to add some animation to -show and -hide if you want it to animate up from the bottom of the screen - I was just too lazy to do this.
iOS 8 added the UIModalPresentationOverFullScreen presentation style. Set this as the presented view controller’s modalPresentationStyle. For more advanced needs, look into creating a custom presentation controller.
There is now a way to achieve this using iOS7 custom transitions :
MyController * controller = [MyController new];
[controller setTransitioningDelegate:self.transitionController];
controller.modalPresentationStyle = UIModalPresentationCustom;
[self controller animated:YES completion:nil];
To create your custom transition, you need 2 things :
A TransitionDelegate object (implementing
<UIViewControllerTransitionDelegate>)
An "AnimatedTransitioning" object
(implementing <UIViewControllerAnimatedTransitioning>)
You can find more informations on custom transitions in this tutorial : http://www.doubleencore.com/2013/09/ios-7-custom-transitions/
Try this:
ViewController *vc = [[ViewController alloc] init];
[vc setModalPresentationStyle:UIModalPresentationOverCurrentContext];
[self presentViewController:vc animated:YES completion:nil];
Have you tried looping over the Modal View Controller's subviews and setting the background color to clear for every view? This is a DFS recursive function.
- (void)setBackgroundToClearForView:(UIView *)view {
if ([view subviews]) {
for (UIView *subView in [view subviews]) {
[self setBackgroundToClearForView:subView];
}
}
if ([view respondsToSelector:#selector(setBackgroundColor:)]) {
[view performSelector:#selector(setBackgroundColor:)
withObject:[UIColor clearColor]];
}
}
To use it call:
[self setBackgroundToClearForView:self.view];
in viewDidLoad.
This will do the trick.. Try this one.
// for clear color or you can easily adjust the alpha here
YourVC *vc=[[YourVC alloc]initWithNibName:#"YourVC" bundle:nil] ;
vc.view.backgroundColor = [UIColor clearColor];
self.modalPresentationStyle = UIModalPresentationCurrentContext;
[self presentViewController:vc animated:NO completion:nil];
So that the view will be full screen unlike UIModalPresentationFormSheet..

UIView disappears after modalViewController is removed from superview

In my app I have a tabBarController and in it a navigationController. One of my view controllers is a TableViewController and under the navigationBar i added a uiView as a subview to the view like this:
rectangleInfo = [[UIView alloc] initWithFrame:CGRectMake(0,0,[[UIScreen mainScreen] applicationFrame].size.width,26)]; rectangleInfo.autoresizingMask = (UIViewAutoresizingFlexibleWidth); rectangleInfo.backgroundColor = [UIColor darkGrayColor]; [self.view addSubview: rectangleInfo];
when I click on a cell in the tableView I push an UIViewController like this:
[feedViewController setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
[[self navigationController] presentModalViewController:feedViewController animated:YES];
After i pop the modal view for a couple of times with it from the tableViewNavigationController disappears the rectangleInfo UIView.
I pop my modalview like this:
[[UIApplication sharedApplication] setStatusBarHidden:NO animated:YES];
[self setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
[self dismissModalViewControllerAnimated:YES];
any idea why that subview (rectangleInfo) of the tableViewController dissapears after i remove the modal view from the superview?
thank you in advance.
I'm curious as to what you are trying to do with your rectangleInfo view? By the size of it, it looks like you are trying to mimic the status bar. Why? You can just hide the status bar if you want.
Another thing you can try is to create the UIView visually in Interface Builder. Don't actually add it to your main view, but create it as a separate UIView in the XIB with the appropriate size, etc. Then create an outlet for it in Xcode and connect it. Next, add it as a subview in code when your view controller loads. See if that makes a difference. This is especially strange since you say it only disappears after popping it several times. Do you get the same problem if you push and pop the non-modal way, e.g.:
[[self navigationController] pushViewController:feedViewController animated:YES];
[[self navigationController] popViewControllerAnimated:YES];
i solved the problem by implementing correctly the viewDidLoad and viewDidUnload methods for creating and releasing my subviews.