Как программно изменить ориентацию устройства в iOS 6
В iOS 5 мы могли программно изменить ориентацию устройства следующим образом:
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight];
Но в iOS 6 setOrientation
устарела, как я могу программно изменить ориентацию устройства в iOS 6?
14 ответов
Вот мои "пять центов", протестированные на iOS7 с ARC
[[UIDevice currentDevice] setValue:
[NSNumber numberWithInteger: UIInterfaceOrientationPortrait]
forKey:@"orientation"];
Это не генерирует предупреждение "утечки", как будет выполнять executeSelector.
UIAlertView - с помощью этого кода, когда вы открываете UIAlertView во время просмотра (будет / делал), вы заметите, что все, кроме этого представления, в портретном (на самом деле, яблоко?), Я не смог заставить вид переориентироваться, но обнаружил, что если Вы устанавливаете небольшую задержку перед открытием UIAlertView, после чего представление успевает изменить ориентацию.
Обратите внимание, что я выпускаю неделю моего приложения, начинающуюся 12/09/2014, и я обновлю сообщение, если оно пройдет или не получится
Это не ответ, как изменить ориентацию устройства, но дополнительную информацию, которая может вам помочь.
Ориентация интерфейса iOS 6 - shouldAutorotateToInterfaceOrientation: не работает
Метод shouldAutorotateToInterfaceOrientation: НЕ поддерживается в iOS 6. Его не рекомендуется. На всякий случай, если вы новичок, который просто смотрел, как работает в какао, и вам интересно, почему ваш контроллер представления испорчен в iOS 6 и идеально подходит в iOS 5, просто знайте, что shouldAutorotateToInterfaceOrientation: больше не поддерживается. Хотя он может хорошо работать с Xcode 4 до 4.3, он не будет работать на Xcode 4.5.
Apple предлагает новый метод, чтобы сделать это гораздо более чистым способом. Вместо этого вы используете supportInterfaceOrientations. Он возвращает все ориентации интерфейса, которые поддерживает контроллер представления, маску значений ориентации интерфейса.
UIInterfaceOrientationMask Enum:
Эти константы являются битами маски для указания поддерживаемых ориентаций интерфейса контроллера представления.
typedef enum {
UIInterfaceOrientationMaskPortrait = (1 << UIInterfaceOrientationPortrait),
UIInterfaceOrientationMaskLandscapeLeft = (1 << UIInterfaceOrientationLandscapeLeft),
UIInterfaceOrientationMaskLandscapeRight = (1 << UIInterfaceOrientationLandscapeRight),
UIInterfaceOrientationMaskPortraitUpsideDown = (1 << UIInterfaceOrientationPortraitUpsideDown),
UIInterfaceOrientationMaskLandscape =
(UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight),
UIInterfaceOrientationMaskAll =
(UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft |
UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskPortraitUpsideDown),
UIInterfaceOrientationMaskAllButUpsideDown =
(UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft |
UIInterfaceOrientationMaskLandscapeRight),
} UIInterfaceOrientationMask;
Использование shouldAutorotateToInterfaceOrientation: метод:
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
return UIInterfaceOrientationIsLandscapeRight(toInterfaceOrientation);
}
Используя метод selectedInterfaceOrientations:
-(NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskLandscapeRight;
}
Это добавленные методы в UIViewController относительно ориентации в iOS6
Добавлены методы для UIApplication относительно ориентации в iOS6
Я обнаружил, что самый простой способ заставить устройство изменить ориентацию - это представить новый контроллер вида (используя presentViewController:animated:completion:
) где новый контроллер представления указал конкретную предпочтительную ориентацию (путем реализации метода -(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
).
Когда новый контроллер представления представлен, как и ожидалось, ориентация изменится на ту, которую предпочитает новый контроллер представления. Итак, простейшая реализация (наилучшая практика?) Будет заключаться в том, чтобы встроить всю необходимую функциональность в определенной ориентации в отдельный контроллер представления и представить ее по мере необходимости. Система позаботится об изменении ориентации для вас.
Очевидно, что это может не подходить для всех случаев использования, но, к счастью, тот же прием применяется для того, чтобы заставить устройство изменить ориентацию для существующего контроллера вида.
Хитрость заключается в том, чтобы представить новый контроллер вида с определенной предпочтительной ориентацией, которая вам нужна, а затем сразу скрыть его. Это приведет к временному изменению ориентации при представлении нового контроллера вида. Лучшая часть, когда новый контроллер представления отклонен, оригинальный (представляющий) контроллер представления preferredInterfaceOrientationForPresentation
запрос снова, вы можете указать конечную ориентацию, которую вы хотите здесь.
Здесь важно обратить внимание и на временное отключение автоматического поворота в исходном контроллере вида (при возврате из недавно представленного, а затем отклоненного контроллера вида), чтобы при повороте телефона пользователем в направлении новой ориентации он не срабатывает дальнейшее автоматическое вращение.
Следующий код должен проиллюстрировать мою точку зрения, мой пример вынуждает вращение к портрету, просто измените соответственно, если вы хотите другую ориентацию
Предполагая, что у вас есть оригинальный контроллер вида с именем Original
и временный контроллер вида с именем ForcePortrait
@interface Original : UIViewController
{
BOOL orientationToPortrait; //should set to NO by default
}
@end
@implementation Original
- (UIInterfaceOrientation) preferredInterfaceOrientationForPresentation
{
if(orientationToPortrait)
{
//when we manually changed, show in Portrait
return UIInterfaceOrientationPortrait;
}
else
{
//before manual orientation change, we allow any orientation
return self.interfaceOrientation;
}
}
-(BOOL) shouldAutorotate
{
//we should 'lock' the rotation once we manually change it
return !orientationToPortrait;
}
-(void) changeOrientationToPortrait
{
//Sample method to change the orientation
//when called, will show (and hide) the temporary view
//Original.preferredInterfaceOrientationForPresentation will be called again after this method
//flag this to ensure that we tell system we prefer Portrait, whenever it asked again
orientationToPortrait = YES;
//presenting the following VC will cause the orientation to temporary change
//when the new VC is dismissed, system will ask what is our (Original) orientation preference again
ForcePortrait* forcePortrait = [[ForcePortrait alloc] init];
[self presentViewController:forcePortrait animated:NO completion:^{
[forcePortrait dismissViewControllerAnimated:NO completion:nil];
}];
}
@end
@interface ForcePortrait : UIViewController
@end
@implementation ForcePortrait
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationPortrait;
}
@end
Попробуй это:
#import <objc/message.h>
if(UIDeviceOrientationIsLandscape(self.interfaceOrientation)){
if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)])
{
objc_msgSend([UIDevice currentDevice], @selector(setOrientation:), UIInterfaceOrientationPortrait );
}
}
Вы должны разместить[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
в вашем AppDelegate didFinishLaunchingWithOptions
Метод.
Затем в любом месте вашего приложения вы можете получить текущую ориентацию с помощью:
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
И проверить ориентацию с:
UIInterfaceOrientationIsPortrait(orientation)
UIInterfaceOrientationIsLandscape(orientation)
подобно
if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation))
{
// code for landscape orientation
// OR
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight];
// OR
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeLeft];
}
else if (UIDeviceOrientationIsPortrait([UIDevice currentDevice].orientation))
{
// code for Portrait orientation
// OR
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationPortraitUpsideDown];
// OR
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationPortrait];
}
Этот код для iOS 8 или новее
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];
@implementation UINavigationController (автоматический поворот)
-(NSUInteger)supportedInterfaceOrientations
{
//make the check for iphone/ipad here
if(IPHONE)
{
return UIInterfaceOrientationMaskPortrait;
}
else
{
return UIInterfaceOrientationMaskLandscape;
}
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationPortrait;
}
- (BOOL)shouldAutorotate
{
return NO;
}
Попробуйте это... Это сработало для меня...
UIWindow *window = [[UIApplication sharedApplication] keyWindow];
UIView *view = [window.subviews objectAtIndex:0];
[view removeFromSuperview]; [window addSubview:view];
Apple сделала программную смену ориентации устройства в ios6 достаточно сложной (специально для вас).
Насколько я знаю, единственный способ выполнить то, что вы просите, - смоделировать изменение ориентации устройства.
С помощью setTransform
вращать UIView
и повторное применение его собственного кадра дает желаемые результаты.
[YourView setTransform:CGAffineTransformMakeRotation(1.57)];
[YourView setFrame:CGRectMake(0, 0, YourView.frame.size.width, YourView.frame.size.height)];
И когда физическая ориентация устройства меняется, мы можем отменить преобразование.
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
[YourView setTransform:CGAffineTransformMakeRotation(0)];
[YourView setFrame:CGRectMake(0, 0, YourView.frame.size.width, YourView.frame.size.height)];
}
Небольшая модификация ответа Бисси, если вы хотите избежать использования Runtime Library:
if (UIDeviceOrientationIsLandscape([[UIDevice currentDevice] orientation]))
{
if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)])
{
int orientationPortrait = UIInterfaceOrientationPortrait;
NSMethodSignature *sig = [[UIDevice currentDevice] methodSignatureForSelector:@selector(setOrientation:)];
NSInvocation* invo = [NSInvocation invocationWithMethodSignature:sig];
[invo setTarget:[UIDevice currentDevice]];
[invo setSelector:@selector(setOrientation:)];
[invo setArgument:&orientationPortrait atIndex:2];
[invo invoke];
}
}
Это работает для iOS7, принудительно поверните в портрет.
//In your viewController.m
#import <objc/message.h>
// for autorotate viewController to portraid
- (void)viewWillAppear:(BOOL)animated {
UIInterfaceOrientation orientationStatusBar =[[UIApplication sharedApplication] statusBarOrientation];
switch (orientationStatusBar) {
case UIInterfaceOrientationPortrait:break;
case UIInterfaceOrientationLandscapeLeft:
objc_msgSend([UIDevice currentDevice], @selector(setOrientation:), UIInterfaceOrientationPortrait);
break;
case UIInterfaceOrientationLandscapeRight:
objc_msgSend([UIDevice currentDevice], @selector(setOrientation:), UIInterfaceOrientationPortrait);
break;
default:
break;
}
}
// this permit autorotate
- (BOOL) shouldAutorotate
{
// this lines permit rotate if viewController is not portrait
UIInterfaceOrientation orientationStatusBar =[[UIApplication sharedApplication] statusBarOrientation];
if (orientationStatusBar != UIInterfaceOrientationPortrait) {
return YES;
}
//this line not permit rotate is the viewController is portrait
return NO;
}
ПРИМЕЧАНИЕ. Я реализовал эту опцию в своем приложении, но, вероятно, Apple ее отклонит (комментарий к Остину, отредактированный 6 из Sergey K. в октябре 2012 года).
if (self.interfaceOrientation != UIInterfaceOrientationLandscapeRight) {
// http://stackru.com/questions/181780/is-there-a-documented-way-to-set-the-iphone-orientation
// http://openradar.appspot.com/radar?id=697
// [[UIDevice currentDevice] setOrientation: UIInterfaceOrientationLandscapeRight]; // Using the following code to get around apple's static analysis...
[[UIDevice currentDevice] performSelector:NSSelectorFromString(@"setOrientation:") withObject:(id)UIInterfaceOrientationLandscapeRight];
}
Интересно, как другие не столкнулись с проблемами после того, как не установили это так:
+ (void)setOrientation:(UIDeviceOrientation)orientation {
[UIDevice.currentDevice setValue:@(orientation) forKey:@"orientation"];
[UIViewController attemptRotationToDeviceOrientation];
[UIDevice.currentDevice setValue:@(UIDeviceOrientationUnknown) forKey:@"orientation"];
}
Мое требование заключалось в том, чтобы иметь возможность принудительно ориентировать, а затем снова повернуть к естественной ориентации устройства... есть UIDeviceOrientationDidChangeNotification, который может предоставить вам информацию об ориентации ведьмы, чтобы повернуть устройство назад, но на самом деле это частично не будет работать, если вы не установите unknown сразу после того, как вы изменили ориентацию в UIDevice, также есть больше деталей, чтобы сделать его крутым, но я оставлю его, так как это выходит за рамки этого простого вопроса.
Это работает для меня на Xcode 6 и 5.
- (BOOL)shouldAutorotate {return YES;}
- (NSUInteger)supportedInterfaceOrientations {return (UIInterfaceOrientationMaskPortrait);}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return NO;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return interfaceOrientation == UIInterfaceOrientationPortrait
|| interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown ;
}