The best solution I've found is to create a transparent container view, add that container to the window, and place your alert inside the container. You may then register for UIApplicationWillChangeStatusBarOrientationNotification to receive rotation events and transform the container; this allows you to independently manipulate the frame of the alert:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
...
self.container = [[UIView alloc] initWithFrame:self.window.bounds];
[self.container addSubview:self.alertView];
[self.window addSubview:self.container];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(statusBarWillRotate:)
name:UIApplicationWillChangeStatusBarOrientationNotification
object:nil];
...
}
...
- (void)statusBarWillRotate:(NSNotification *)theNotification
{
CGFloat rotation = 0;
switch ([notification[UIApplicationStatusBarOrientationUserInfoKey] intValue])
{
case UIInterfaceOrientationLandscapeLeft:
rotation = -M_PI_2;
break;
case UIInterfaceOrientationLandscapeRight:
rotation = M_PI_2;
break;
case UIInterfaceOrientationPortraitUpsideDown:
rotation = M_PI;
break;
case UIInterfaceOrientationPortrait:
default:
rotation = 0;
break;
}
CGAffineTransform rotationTransform = CGAffineTransformMakeRotation(rotation);
CGSize rotatedSize = CGRectApplyAffineTransform(self.window.bounds, rotationTransform).size;
[UIView animationWithDuration:[UIApplication sharedApplication].statusBarOrientationAnimationDuration
animations:^{
self.container.transform = rotationTransform;
// Transform invalidates the frame, so use bounds/center
self.container.bounds = CGRectMake(0, 0, rotatedSize.width, rotatedSize.height);
self.container.center = CGPointMake(self.window.bounds.size.width / 2, self.window.bounds.size.height / 2);
}];
}
You can, if you really want, create an entirely new window with its windowLevel property set to UIWindowLevelAlert, which will guarantee that the window remain above all other views, including the keyboard, but window management gets a littly tricky. The above solution should suffice for most needs.
The problem with simply adding a view controller's view to a window is that it is not guaranteed to receive all the rotation and view[Will|Did][Disa|A]ppear: messages unless it is added to the view controller hierarchy via addChildViewController: on the root view controller.