iPad modal view's rect within the main window - ios

I am presenting a modal view (with UIModalPresentationFormSheet) on top of a UISplitViewController. I want to get the exact rect that the modal view will take relative to the UISplitViewController (which is basically the whole window). i.e. the modal view is at x,y coordinate and the size.
How would I find this? I looked at UIView's "convertRect:fromView:" method, but couldn't figure out what combination would work.
Thanks.

[splitView convertRect:modallyPresentedVC.view.bounds fromView:modallyPresentedVC.view] should do the trick. Make sure to call it in the completion block of the presentation (after all animation has finished).

Related

UITabBarController's tabs' rotation and willRotateToInterfaceOrientation propagartion

My app has four tabs: A, B, C and D. Their UIViewController are managed by UITabBarController. The app supports rotation, and so each view controller returns YES to shouldAutorotateToInterfaceOrientation.
Using springs and struts, most of the rotation is done automatically by iOS. However, tab A also requires further positioning, and it is done in its VC's willRotateToInterfaceOrientation method.
When the VC for tab A is selected and the screen is rotated, that VC receives a willRotateToInterfaceOrientation message (propagated by iOS from UITabBarController), and the resulting rotation is correct.
However, when the selected tab is B and the screen is rotated, A's willRotateToInterfaceOrientation is not called. Makes sense. But if I then select tab A, I get only the results of applying its springs and struts, without the post-processing done by its willRotateToInterfaceOrientation.
After struggling with this for a while, and after failing to find a solution online, I came up with the following. I subclassed UITabBarController and in its willRotateToInterfaceOrientation I call all the VCs' willRotateToInterfaceOrientation regardless of which one is the selectedViewController:
- (void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
if (self.viewControllers != nil) {
for (UIViewController *v in self.viewControllers)
[v willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
}
}
It works, but it looks like a hack, and my question is whether I was doing the right thing. Is there a way to tell iOS to always call a VC's willRotateToInterfaceOrientation before displaying it for the first time after a screen rotation?
The best way to handle custom layout is by subclassing UIView and overriding the layoutSubviews method. The system sends layoutSubviews to a view whenever its size is changed (and at other times). So when your view A is about to appear on screen with a different size (because the interface was rotated while view B was on screen), the system sends view A a layoutSubviews message, even though it doesn't send view controller A a willRotateToInterfaceOrientation: message.
If you are targeting iOS 5.0 or later, you can override the viewDidLayoutSubviews method of your UIViewController subclass and do your layout there, instead of subclassing UIView. I prefer to do it in my view's layoutSubviews, to keep my view-specific logic separate from my control logic.
It's also a bad idea to do layout in willRotateToInterfaceOrientation: because the system sends that message before actually changing the size of the view, and before the rotation animation block. It sends the willAnimateRotationToInterfaceOrientation:duration:, layoutSubviews, and viewDidLayoutSubviews messages inside the rotation animation block, so the repositioning of your subviews will be animated if the view is on screen during the rotation.

When dismissing a fullscreen modal the viewWillLayoutSubviews method does not get called

I am trying to track down a problem where the viewWillLayoutSubviews (and viewDidLayoutSubviews) method do not get called after dismising a controller displayed using -
[self presentModalViewController:controller animated:YES];
and dismissing with
[self dismissModalViewControllerAnimated:YES];.
This view controller is displayed on top of a UISplitViewController as the result of a button being pressed in the detail area. When I rotate the device, without the modal up, I do get the viewWillLayoutSubviews callback. However, the problem is, when I rotate during the presentation of the model, it does not update the views correctly and recalculate the view bounds after dismissing it. According to the IOS 5 release notes I should get a viewDidLayoutSubviews after dismissing the modal view controller.
For comparison, I created a bare bones app with none of my other code in it and it works as documented, it will call viewWillLayoutSubviews after the modal is dismissed.
I have been going over and over my real app code and can't find anything wrong. I am looking for suggestions for things to do help figure this out. Why would the callback work when rotating but not work when the modal is dismissed? Could it be something with my view hierarchy?
Thanks for any help!
Try using the delegate method viewWillAppear instead of viewWillLayoutSubviews. The WillLayoutSubviews is only called when the view's bounds change (which happens when you rotate the device).

what method is called after view is rotated

I want to change position of UIPopover after the view is rotated. can you tell me what method is called after view is rotated so that I can get the coordinates of UI elments in the final view rendered after rotation of view
popover behavior in any Apples native application. You'll see that in response to device rotation popover should disappear before rotation animation and appear again on new appropriate place after it ends. So you should dismiss your popover and then popup it on new place with new coordinates (how to get these coordinates)
Thanx in advance
From the docs for -[UIViewController didRotateFromInterfaceOrientation:]:
Sent to the view controller after the user interface rotates. … Subclasses may override this method to perform additional actions immediately after the rotation. … By the time this method is called, the interfaceOrientation property is already set to the new orientation.

UIPopoverController Not Animating

I have an iPad app that has an MKMapView embedded in a UINavigationController which is displayed in a UITabBar. I am displaying a popover controller over the map with
UIPopoverController *myPopoverController =
[[[UIPopoverController alloc] initWithContentViewController:myContentView]
autorelease];
[myPopoverController presentPopoverFromRect:myRect
inView:mapView
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
The popover displays fine. However, it does not have the nice animated effect: it just immediately appears onscreen. Similarly, when I dismiss it it just disappears without any animation.
Anybody have any idea how I can get the animation to work? Should I try displaying it from another view? Is there some property on something that I might have neglected to set?
Despite the animated:(BOOL) parameter, it appears popovers never animate when presented. I've tried a dozen first and third party apps.
The dismissal should animate however, provided you pass YES to dismissPopoverAnimated:(BOOL)
Assuming your popover animates outside the map view, I would try placing the map view into a container view whose frame is the same size as the map view's. From there, it's trivial to present the popover in the container view.
According to Apple's documentation, MKMapView isn't supposed to be subclassed, so like UIWebView, it strikes me as one of those views whose guts are better left untouched.

iPad Partial Curl modal transition always curls to full screen

I'm using UIModalTransitionStylePartialCurl to show a modal view in iPad.
modalViewController.modalTransitionStyle = UIModalTransitionStylePartialCurl;
[[self parentViewController] presentModalViewController:modalViewController animated:YES];
self is the right side view controller of my SplitViewController.
When I do this, the page is curled all the way to the top even though the size of the view of modalViewController is small. I only need it to curl a little so it would reveal ONLY the area taken by modalViewController. What I'm trying to do is something exactly like the iPad maps application settings.
I tried using all the modalPresentationStyle options for the modal view and I also tried setting the modalPresentationStyle.view.frame to a small CGRect but still couldn't get it to work.
Can anybody help on this...thanks in advance..
Just leave a clean space (No Controls or Images) in the top of your PresentedViewController, the Framework make the rest.
I have yet to find a more optimal solution, but I've been able to get good results by making the modal (revealed) view the same size as the parent (curling) view. iOS looks at the subviews to determine where to stop the curling and shows "just enough" of the subview to keep the subview pieces on-screen.

Resources