I have this method in my MainViewController:
-(void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
NSLog(#"MAIN CONTAINER WILL ANIMATE");
[super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
}
And when I rotate, the NSLog shows up, and everything is perfect. However, if I present a modalViewController from my MainViewController, and then I rotate, the NSLog no longer appears, and my MainViewController never knows that the device got rotated, so when the modalView is dismissed, the interface is not adjusted for the rotation.
Any ideas as to why a modal view can prevent the parent from receiving rotation updates? Is this typical, or must there be something wrong with my setup?
And just to make sure, I tried presenting the modalViewController as a subview via [mainViewController.view addSubview:modalView.view], and the rotation updates took effect properly. It's only when I do [mainViewController presentModalViewController:modalViewController]; that the updates don't take effect.
Surely when a view controller is being presented modally, no other view controllers receive any messages at all. That is what modal means in this context.
The obvious solution would be to check the orientation in the viewWillAppear method of your modeless view controller.
You have to check the implementation of:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Overriden to allow any orientation.
return YES;
}
In both views.
You need to adjust your layout to the current interface orientation in viewWillAppear. Obviously, because the view is not visible, the animation functions will not be called while the modal view controller is up.
Related
I am using IIViewDeckController and facing a very weird problem as follows?:
My ViewController(which is an IIViewDeckController) is in landscape mode and then I present a new view controller modally on top of it. Now the modal view controller does not support landscape mode and thus is presented only in portrait mode.
As of now, everything went fine.
But as soon as I try to dismiss this modally presented controller, IIViewDeckController's view's frame becomes (320,568) (I think this IIViewDeckController has rotated to portrait mode but I am not sure for that). So I checked self.interfaceOrientation which showed "4"(i.e. UIInterfaceOrientationLandscapeLeft) which should be the actual case.
But these two things are confusing me as the frame is indicating the portrait mode and property shows something different. Now because of this frame changing without changing the interfaceOrientation is result into wrong calculation of objects' frames in the view.
I faced the same problem, I solved it by categorizing IIViewDeckController inside AppDelegate class.
Following is the one method that was required to be categorized:-
#interface IIViewDeckController (categoryForOrientation)
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation;
#end
#implementation IIViewDeckController (categoryForOrientation)
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
return [self interfaceOrientation];
}
I have a UIViewController, which launches a modal view controller. Both have orientation support. If i rotate with the modal view controller there, it doesn't tell the view controller behind it that rotation has happened, and so when the modal view controller is dismissed, the original view is in the right orientation, but at the original sizes (e.g. i rotate it to be 480x320, the text and other items will be the correct way up for the new orientation, but will still be arranged in their 320x480 layout). How do i let the view controller know rotation has occurred?
use NSNotification.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// send a notification here
}
In your ViewController behind, add an observer and call a method to fix the layout.
An old SO answer explaining the sytntax for NSNotification
I hope its useful
I have a view controller which manages a view.
I'm adding the my view controller subclass as a subview of the window swapping out another view.
I'm running landscape mode on an iPad.
The view apparently doesn't know that its in landscape mode. Its frame is confused.
Is there something I can/should do to tell it that its in landscape, and/or that the orientation has changed. How does this normally happen. Why isn't it happening?
I used to have my view controller within a UITabBarController and it worked fine there.
Override:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return YES;
}
Your ViewController is not getting rotation events because you have not presented the viewController but have added the viewController's view in the view hierarchy.
Your Tab bar controller previously used to take the responsibility to forward the rotation events to the view controller which it manages, that was how it used to work.
I would though suggest that swapping the view out of window is a bad idea. Instead you should have a main viewController which accepts the rotation events and then swap the view within this viewController based on the current orientation. Consider re-desiging before you code further.
My problem was that my storyboard was overriding my existing custom coded app delegate. After I deleted the story board file, and custom generated view controller code, it worked for me.
How can I detect the end of the animation of a modal view (when I do a dismiss)? (I'm talking about MFMailComposeViewController which is not created by myself...)
Thanks
Your modal view controller has a -viewDidDisappear: method that is automatically invoked whenever the view is removed from the screen. You can override this method in your modal view controller to do whatever you like.
Also, you may want to consider implementing the -viewDidAppear: method in the view controller whose view gets revealed by your modal view disappearing.
You can subclass MFMailComposeViewController and overload its -viewDidDisappear:.
#interface MyCtrler : MFMailComposeViewController
#end
#implementation MyCtrler
-(void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
// do anything you like
}
#end
I needed to do something after dismissing a modal view, and only when it is sure that the modal view is really gone (been completely dealloc-ed). So viewDidDisappear and its friends in the modal view were too early for me.
The easiest I found was to just delay my code with a NSTimer. When modal view calls its delegate and the delegate invokes removing the modal view, it also queues up the code to be run when the modal view is gone. The timing was something like 300ms or 400ms. (Is there a way to retrieve the actual timing from somewhere?)
Normally to be notified when an animation is complete you set a delegate by sending setAnimationDelegate: to the UIView class.
When a VC is dismissed using [someVC dismissModalViewControllerAnimated:YES] you can't set the animation delegate, but if you send NO instead and do your own animation of the VC's view you can set the delegate and be notified when the animation is completed.
a short question.
I've created an app for the iPad, much like a utility app for the iPhone (one mainView, one flipSideView). The animation between them is UIModalTransitionStylePartialCurl.
shouldAutorotateToInterfaceOrientation is returning YES.
If I rotate the device BEFORE entering the FlipSide, everything is okay and the PartialCurl is displayed okay.
But if I enter the FlipSide and then rotate the device, while the UIElements do rotate and position themselves just fine, the actual "page curl" stays with its initial orientation. it just won't budge :)
Is it a known issue? am I doing something wrong?
Thanks!
I too had this issue and somewhat gave up. However, I mentioned my dilemma to a friend, who encouraged me to look into the child VC's logic and I recalled a handy trick that I've used to pass data between parent/child view controllers.
In your flipside view controller, create a "rootViewController" property. In your parent view controller, when you initialize the flipside view controller, you set (where "self" is the rootVC):
flipsideController.rootViewController = self;
You then use this for your flipside VC's shouldAutorotateToInterfaceOrientation method:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return interfaceOrientation == self.rootViewController.interfaceOrientation;
}
Viola! The flipside view no longer rotates underneath the partially curled up parent view!
The shortest way of the above code is:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return interfaceOrientation == self.parentViewController.interfaceOrientation;
}