Есть ли документальный способ настройки ориентации iPhone?

У меня есть приложение, в котором я хотел бы поддерживать поворот устройства в определенных представлениях, но другие особенно не имеют смысла в ландшафтном режиме, поэтому, когда я заменяю представления, я хотел бы заставить поворот быть установленным на портрет.

На UIDevice есть недокументированный набор свойств, который делает трюк, но, очевидно, генерирует предупреждение компилятора и может исчезнуть с будущей версией SDK.

[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationPortrait]; 

Существуют ли какие-либо документированные способы принудительной ориентации?

Обновление: я думал, что приведу пример, поскольку я не ищу shouldAutorotateToInterfaceOrientation, как я уже это сделал.

Я хочу, чтобы мое приложение поддерживало пейзаж и портрет в представлении 1, но только портрет в представлении 2. Я уже реализовал shouldAutorotateToInterfaceOrientation для всех представлений, но если пользователь находится в ландшафтном режиме в представлении 1, а затем переключается на вид 2, я хочу заставить для поворота назад в положение «Портрет».

Это уже не проблема на более позднем iPhone 3.1.2 SDK. Похоже, что он соблюдает запрошенную ориентацию вида, отбрасываемого назад в стек. Вероятно, это означает, что вам нужно будет обнаружить более старые версии ОС для iPhone и применять приложение setOrientation только до последней версии.

Неясно, будет ли статический анализ Apple понимать, что вы работаете над более старыми ограничениями SDK. Я лично сказал Apple, чтобы удалить вызов метода в моем следующем обновлении, поэтому я еще не уверен, что если взломать старые устройства будет проходить процесс утверждения.

Это происходит долго после этого факта, но на всякий случай приходит кто-то, кто не использует навигационный controller и / или не хочет использовать недокументированные методы:

 UIViewController *c = [[UIViewController alloc]init]; [self presentModalViewController:c animated:NO]; [self dismissModalViewControllerAnimated:NO]; [c release]; 

Достаточно представить и отклонить controller просмотра ванили.

Очевидно, вам все равно нужно подтвердить или отклонить ориентацию в вашем переопределении shouldAutorotateToInterfaceOrientation. Но это приведет к тому, что wasAutorotate … будет снова вызван системой.

Если вы хотите заставить его вращаться с портрета на пейзаж, вот код. Просто отметьте, что вам нужно настроить центр своего вида. Я заметил, что мое место не поместило точку зрения в нужное место. В противном случае он работал отлично. Спасибо за совет.

 if(UIInterfaceOrientationIsLandscape(self.interfaceOrientation)){ [UIView beginAnimations:@"View Flip" context:nil]; [UIView setAnimationDuration:0.5f]; [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; self.view.transform = CGAffineTransformIdentity; self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(90)); self.view.bounds = CGRectMake(0.0f, 0.0f, 480.0f, 320.0f); self.view.center = CGPointMake(160.0f, 240.0f); [UIView commitAnimations]; } 

Из того, что я могу сказать, метод setOrientation: не работает (или, возможно, больше не работает). Вот что я делаю для этого:

во-первых, укажите это в верхней части вашего файла, прямо под вашим #imports:

 #define degreesToRadian(x) (M_PI * (x) / 180.0) 

то в viewWillAppear: метод

 [[UIApplication sharedApplication] setStatusBarHidden:YES animated:NO]; if (self.interfaceOrientation == UIInterfaceOrientationPortrait) { self.view.transform = CGAffineTransformIdentity; self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(90)); self.view.bounds = CGRectMake(0.0, 0.0, 480, 320); } 

если вы хотите, чтобы это было анимировано, вы можете обернуть все это в блок анимации, например:

 [UIView beginAnimations:@"View Flip" context:nil]; [UIView setAnimationDuration:1.25]; [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; [[UIApplication sharedApplication] setStatusBarHidden:YES animated:NO]; if (self.interfaceOrientation == UIInterfaceOrientationPortrait) { self.view.transform = CGAffineTransformIdentity; self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(90)); self.view.bounds = CGRectMake(0.0, 0.0, 480, 320); } [UIView commitAnimations]; 

Затем, в вашем диспетчере портрета, вы можете выполнить обратную проверку, чтобы увидеть, находится ли в данный момент пейзаж, и если да, верните его обратно в положение «Портрет».

У меня была проблема, когда у меня был UIViewController на экране, в UINavigationController , в альбомной ориентации. Тем не менее, когда controller следующего представления вдвинут в stream, мне нужно, чтобы устройство вернулось к портретной ориентации.

Я заметил, что метод shouldAutorotateToInterfaceOrientation: не вызывается, когда новый controller представлений shouldAutorotateToInterfaceOrientation: в стек, но он вызывается, когда из стека вызывается controller вида .

Воспользовавшись этим, я использую этот fragment кода в одном из моих приложений:

 - (void)selectHostingAtIndex:(int)hostingIndex { self.transitioning = YES; UIViewController *garbageController = [[[UIViewController alloc] init] autorelease]; [self.navigationController pushViewController:garbageController animated:NO]; [self.navigationController popViewControllerAnimated:NO]; BBHostingController *hostingController = [[BBHostingController alloc] init]; hostingController.hosting = [self.hostings objectAtIndex:hostingIndex]; [self.navigationController pushViewController:hostingController animated:YES]; [hostingController release]; self.transitioning = NO; } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation { if (self.transitioning) return (toInterfaceOrientation == UIInterfaceOrientationPortrait); else return YES; } 

В принципе, создав пустой controller представления, нажав его в стек и сразу же вытащив его, можно вернуть интерфейс в положение портрета. Как только controller выскочил, я просто нажимаю на controller, который я намеревался нажать в первую очередь. Визуально это выглядит великолепно – пустой, произвольный controller просмотра никогда не видит пользователя.

Существует простой способ программно заставлять iPhone иметь необходимую ориентацию – используя два из уже предоставленных ответов kdbdallas , Джош :

 //will rotate status bar [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight]; //will re-rotate view according to statusbar UIViewController *c = [[UIViewController alloc]init]; [self presentModalViewController:c animated:NO]; [self dismissModalViewControllerAnimated:NO]; [c release]; 

работает как шарм 🙂

РЕДАКТИРОВАТЬ:

для iOS 6 Мне нужно добавить эту функцию: (работает в modal viewcontroller)

 - (NSUInteger)supportedInterfaceOrientations { return (UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight); } 

Я копал и копал, ища подходящее решение. Нашел это сообщение в блоге, которое делает трюк: удалите свой внешний вид из ключа UIWindow и добавьте его снова, система затем повторно запросит методы shouldAutorotateToInterfaceOrientation: от ваших controllerов view, обеспечив правильную ориентацию, которая будет применяться. Посмотрите: iphone заставляет uiview переориентировать

Ответ Джоша отлично подходит для меня.

Тем не менее, я предпочитаю публиковать уведомление об изменении ориентации, пожалуйста, обновите UI . Когда это уведомление получено controllerом представления, он вызывает shouldAutorotateToInterfaceOrientation: позволяя вам установить любую ориентацию, вернув YES для shouldAutorotateToInterfaceOrientation: ориентации.

 [[NSNotificationCenter defaultCenter] postNotificationName:UIDeviceOrientationDidChangeNotification object:nil]; 

Единственная проблема заключается в том, что это приводит к переориентации без анимации. Вам нужно будет обернуть эту строку между beginAnimations: и commitAnimations чтобы добиться плавного перехода.

Надеюсь, это поможет.

FWIW, вот моя реализация ориентации вручную (для входа в controller корневого представления вашего приложения, natch):

 -(void)rotateInterfaceToOrientation:(UIDeviceOrientation)orientation{ CGRect bounds = [[ UIScreen mainScreen ] bounds ]; CGAffineTransform t; CGFloat r = 0; switch ( orientation ) { case UIDeviceOrientationLandscapeRight: r = -(M_PI / 2); break; case UIDeviceOrientationLandscapeLeft: r = M_PI / 2; break; } if( r != 0 ){ CGSize sz = bounds.size; bounds.size.width = sz.height; bounds.size.height = sz.width; } t = CGAffineTransformMakeRotation( r ); UIApplication *application = [ UIApplication sharedApplication ]; [ UIView beginAnimations:@"InterfaceOrientation" context: nil ]; [ UIView setAnimationDuration: [ application statusBarOrientationAnimationDuration ] ]; self.view.transform = t; self.view.bounds = bounds; [ UIView commitAnimations ]; [ application setStatusBarOrientation: orientation animated: YES ]; } 

в сочетании со следующим методом UINavigationControllerDelegate (при условии, что вы используете UINavigationController ):

 -(void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated{ // rotate interface, if we need to UIDeviceOrientation orientation = [[ UIDevice currentDevice ] orientation ]; BOOL bViewControllerDoesSupportCurrentOrientation = [ viewController shouldAutorotateToInterfaceOrientation: orientation ]; if( !bViewControllerDoesSupportCurrentOrientation ){ [ self rotateInterfaceToOrientation: UIDeviceOrientationPortrait ]; } } 

Это касается поворота корневого представления в зависимости от того, поддерживает ли входящий UIViewController текущую ориентацию устройства. Наконец, вы захотите подключить rotateInterfaceToOrientation к фактическим изменениям ориентации устройства, чтобы имитировать стандартную функциональность iOS. Добавьте этот обработчик событий в тот же controller корневого представления:

 -(void)onUIDeviceOrientationDidChangeNotification:(NSNotification*)notification{ UIViewController *tvc = self.rootNavigationController.topViewController; UIDeviceOrientation orientation = [[ UIDevice currentDevice ] orientation ]; // only switch if we need to (seem to get multiple notifications on device) if( orientation != [[ UIApplication sharedApplication ] statusBarOrientation ] ){ if( [ tvc shouldAutorotateToInterfaceOrientation: orientation ] ){ [ self rotateInterfaceToOrientation: orientation ]; } } } 

Наконец, зарегистрируйтесь для уведомлений UIDeviceOrientationDidChangeNotification в init или loadview следующим образом:

 [[ NSNotificationCenter defaultCenter ] addObserver: self selector: @selector(onUIDeviceOrientationDidChangeNotification:) name: UIDeviceOrientationDidChangeNotification object: nil ]; [[ UIDevice currentDevice ] beginGeneratingDeviceOrientationNotifications ]; 

Это работает для меня (спасибо Henry Cooke):

objective для меня состояла в том, чтобы иметь дело только с изменениями ландшафтной ориентации.

метод init:

 [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil]; 

 - (void)orientationChanged:(NSNotification *)notification { //[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications]; UIDeviceOrientation orientation = [UIDevice currentDevice].orientation; CGRect bounds = [[ UIScreen mainScreen ] bounds ]; CGAffineTransform t; CGFloat r = 0; switch ( orientation ) { case UIDeviceOrientationLandscapeRight: r = 0; NSLog(@"Right"); break; case UIDeviceOrientationLandscapeLeft: r = M_PI; NSLog(@"Left"); break; default:return; } t = CGAffineTransformMakeRotation( r ); UIApplication *application = [ UIApplication sharedApplication ]; [ UIView beginAnimations:@"InterfaceOrientation" context: nil ]; [ UIView setAnimationDuration: [ application statusBarOrientationAnimationDuration ] ]; self.view.transform = t; self.view.bounds = bounds; [ UIView commitAnimations ]; [ application setStatusBarOrientation: orientation animated: YES ]; } по - (void)orientationChanged:(NSNotification *)notification { //[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications]; UIDeviceOrientation orientation = [UIDevice currentDevice].orientation; CGRect bounds = [[ UIScreen mainScreen ] bounds ]; CGAffineTransform t; CGFloat r = 0; switch ( orientation ) { case UIDeviceOrientationLandscapeRight: r = 0; NSLog(@"Right"); break; case UIDeviceOrientationLandscapeLeft: r = M_PI; NSLog(@"Left"); break; default:return; } t = CGAffineTransformMakeRotation( r ); UIApplication *application = [ UIApplication sharedApplication ]; [ UIView beginAnimations:@"InterfaceOrientation" context: nil ]; [ UIView setAnimationDuration: [ application statusBarOrientationAnimationDuration ] ]; self.view.transform = t; self.view.bounds = bounds; [ UIView commitAnimations ]; [ application setStatusBarOrientation: orientation animated: YES ]; } 

У меня есть приложение, в котором я хотел бы поддерживать поворот устройства в определенных представлениях, но другие особенно не имеют смысла в ландшафтном режиме, поэтому, когда я заменяю представления, я хотел бы заставить поворот быть установленным на портрет.

Я понимаю, что вышеупомянутый исходный пост в этой ветке очень старый, но у меня была с ним аналогичная проблема, т. Е. все экраны в моем приложении – только портреты, за исключением одного экрана, который пользователь может поворачивать между пейзажем и портретом.

Это было достаточно просто, но, как и другие сообщения, я хотел, чтобы приложение автоматически возвращалось к портрету, независимо от текущей ориентации устройства, при возврате на предыдущий экран.

Решением, которое я реализовал, было скрытие навигационной панели в ландшафтном режиме, что означает, что пользователь может вернуться только на предыдущие экраны во время портретной работы. Поэтому все остальные экраны могут быть только в портретной ориентации.

 - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)pInterfaceOrientation { BOOL lHideNavBar = self.interfaceOrientation == UIInterfaceOrientationPortrait ? NO : YES; [self.navigationController setNavigationBarHidden:lHideNavBar animated:YES]; } 

Это также имеет дополнительное преимущество для моего приложения, поскольку в ландшафтном режиме доступно больше места на экране. Это полезно, потому что рассматриваемый экран используется для отображения файлов PDF.

Надеюсь это поможет.

В конце концов я решил это довольно легко. Я пробовал каждое предложение выше и все еще придумал короткий, так что это было мое решение:

В ViewController, который должен оставаться Landscape (Left или Right), я слушаю изменения ориентации:

  [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didRotate:) name:UIDeviceOrientationDidChangeNotification object:nil]; 

Затем в didRotate:

 - (void) didRotate:(NSNotification *)notification { if (orientationa == UIDeviceOrientationPortrait) { if (hasRotated == NO) { NSLog(@"Rotating to portait"); hasRotated = YES; [UIView beginAnimations: @"" context:nil]; [UIView setAnimationDuration: 0]; self.view.transform = CGAffineTransformIdentity; self.view.transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(-90)); self.view.bounds = CGRectMake(0.0f, 0.0f, 480.0f, 320.0f); self.view.frame = CGRectMake(0.0f, 0.0f, 480.0f, 320.0f); [UIView commitAnimations]; } } else if (UIDeviceOrientationIsLandscape( orientationa)) { if (hasRotated) { NSLog(@"Rotating to lands"); hasRotated = NO; [UIView beginAnimations: @"" context:nil]; [UIView setAnimationDuration: 0]; self.view.transform = CGAffineTransformIdentity; self.view.transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(0)); self.view.bounds = CGRectMake(0.0f, 0.0f, 320.0f, 480.0f); self.view.frame = CGRectMake(0.0f, 0.0f, 320.0f, 480.0f); [UIView commitAnimations]; } } 

Имейте в виду любые Super Views / Subviews, которые используют авторезистентность, поскольку view.bounds / frame сбрасываются явно …

Единственное предостережение в этом методе сохранения пейзажа «Пейзаж» – это неотъемлемая анимация переключения между ориентациями, которые должны произойти, когда было бы лучше, если бы у нее не было никаких изменений.

Решение iOS 6:

 [[[self window] rootViewController] presentViewController:[[UIViewController alloc] init] animated:NO completion:^{ [[[self window] rootViewController] dismissViewControllerAnimated:NO completion:nil]; }]; 

Точный код зависит от каждого приложения, а также от места его размещения (я использовал его в своем AppDelegate). Замените [[self window] rootViewController] тем, что вы используете. Я использовал UITabBarController .

Я нашел решение и написал что-то по-французски (но код написан на английском языке). Вот

Путь заключается в том, чтобы добавить controller в окно (controller должен обладать хорошей реализацией функции shouldRotate ….).

Если вы используете UIViewControllers, существует такой метод:

 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 

Верните NO для controllerов представления, содержащих просмотры, которые вы не хотите вращать.

Больше информации здесь

Я не думаю, что это можно сделать во время выполнения, хотя вы, конечно, можете применить 90-gradleусное преобразование к своему пользовательскому интерфейсу.

Это то, что я использую. (Вы получаете некоторые компиляционные предупреждения, но это работает как в Simulator, так и в iPhone)

 [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight]; [[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight]; 
  • Open Source Cocoa / Cocoa-Touch POP3 / SMTP библиотека?
  • Создайте случайную буквенно-цифровую строку в Cocoa
  • Округленный UIView с использованием CALayers - только некоторые углы - как?
  • Простое обнаружение движения iPhone
  • Потяните, чтобы обновить UITableView без UITableViewController
  • Как я могу изменить NSArray в Objective-C?
  • установить фоновое изображение для всего приложения iPhone / iPad
  • Лучшая производительность с помощью libxml2 или NSXMLParser на iPhone?
  • iTunes Connect API
  • Как вы можете читать файлы MIME-типа в объективе-c
  • Добавить UIView над всеми другими видами, включая StatusBar
  • Давайте будем гением компьютера.