I have a UIView which is supposed to cover the whole device (UIWindow) to support an image zoom in/out effect I\'m doing using core animation where a user taps a button on a
Another solution how I solved this problem.
Define the current Orientation:
@interface AJImageCollectionViewController (){
UIInterfaceOrientation _currentOrientation;
}
@end
Then check the orientation in the viewWillLayoutSubviews:
- (void)viewWillLayoutSubviews {
[self checkIfOrientationChanged];
}
- (void)checkIfOrientationChanged {
UIInterfaceOrientation newOrientation = [[UIApplication sharedApplication] statusBarOrientation];
BOOL newOrientationIsPortrait = UIInterfaceOrientationIsPortrait(newOrientation);
BOOL oldOrientationIsPortrait = UIInterfaceOrientationIsPortrait(_currentOrientation);
// Check if the orientation is the same as the current
if(newOrientationIsPortrait != oldOrientationIsPortrait){
_currentOrientation = newOrientation;
// Do some stuff with the new orientation
}
}
I had a similar problem with views being added directly to a window. Maybe this will help: Automatically Sizing UIView after Adding to Window
Beginning with iOS 6, only the topmost view controller (alongside the UIApplication object) participates in deciding whether to rotate in response to a change of the device's orientation.
https://developer.apple.com/library/content/qa/qa1688/_index.html
I have open sourced a pod named AGWindowView.
It will automatically deal with any rotation and framechanges so you won't have to worry about that.
It supports any combination of SDK's and iOS system versions. The relevant code can be found here: https://github.com/hfossli/AGWindowView/blob/master/Source/AGWindowView.m
You can read about some of the possible causes here:
Technical Q&A QA1688 - Why won't my UIViewController rotate with the device?
In your situation its probably the fact that you are adding the view as another subview to the window. Only the first subview gets the rotation events. What you can do is add it as a subview of the first window subview.
UIWindow* window = [UIApplication sharedApplication].keyWindow;
if (!window)
window = [[UIApplication sharedApplication].windows objectAtIndex:0];
[[[window subviews] objectAtIndex:0] addSubview:myView];
I created a category on UIApplication that has a helper property and method for getting the first subview of the keyWindow. This is the view you want to overlay anyway. Now when you add a view that is managed by a UIViewController to that view, the shouldRotateToInterfaceOrientation: method is called.
UIApplication+WindowOverlay.h
#import <UIKit/UIKit.h>
@interface UIApplication(WindowOverlay)
@property (nonatomic, readonly) UIView *baseWindowView;
-(void)addWindowOverlay:(UIView *)view;
@end
UIApplication+WindowOverlay.m
#import "UIApplication+WindowOverlay.h"
@implementation UIApplication(WindowOverlay)
-(UIView *)baseWindowView{
if (self.keyWindow.subviews.count > 0){
return [self.keyWindow.subviews objectAtIndex:0];
}
return nil;
}
-(void)addWindowOverlay:(UIView *)view{
[self.baseWindowView addSubview:view];
}
@end
and here is how you would use it.
//at the top of the file...or in {yourproject}.pch
#import "UIApplication+WindowOverlay.h
//in a method:
UIView *view = [UIView new];
UIView *window = [UIApplication sharedApplication].baseWindowView;
view.frame = window.bounds;
[window addSubview:view];
//or
[[UIApplication sharedApplication] addWindowOverlay:view];
This is because as you mention your view has been added directly to the UIWindow, therefore when the method to rotate is called for the navigation controller nothing happens to the uiview. The UIView would rotate if it was a subview of the view controller view. If for some reason this cannot be done. Then you could override this method:
// This method is called every time the device changes orientation
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
}
And every time your orientation changes also change your view orientation.