как программно установить ориентацию устройства в ios 7?

<p>я работаю над приложением для ipad, используя autolayout, где, если пользователь включает определенный режим (режим «голова-вверх»), я хочу поддерживать только портретную (или портретную вверх ногами) ориентацию и, более того, если устройство находится в пейзаж, я хотел бы автоматически переключиться в портретный режим.</p><p>в контроллере вида сверху у меня есть следующее:</p><pre><code>- (nsuinteger) supportedinterfaceorientations { if (self.modeheadsup) { return uiinterfaceorientationmaskportrait | uiinterfaceorientationmaskportraitupsidedown; } else { return uiinterfaceorientationmaskall; } } - (bool) shouldautorotate { return true; } </code></pre><p>основываясь на ответах, которые я видел здесь в другом месте, ответ<em> кажется </em>заключается в том, что я должен использовать "application setstatusbarorientation". поэтому в методе, в котором пользователь выбрал режим «один на один», я включил:</p><pre><code> uiapplication *application = [uiapplication sharedapplication]; [application setstatusbarorientation:uiinterfaceorientationportrait animated:yes]; </code></pre><p>тем не менее, это просто ничего не делает. хотя я могу физически переместить устройство, чтобы оно повернулось в портретное положение, оно не делает это автоматически.</p><p>на самом деле, когда в ландшафтном режиме после выполнения вышеуказанного кода попытка программно установить ориентацию, когда я запрашиваю приложение «statusbarorientation» со следующим кодом, оно остается на «4» для ландшафтного: </p><pre><code>uiapplication *application = [uiapplication sharedapplication]; int orientation = [application statusbarorientation]; self.movestextview.text = [nsstring stringwithformat:@"orientation %d", orientation]; </code></pre><p>казалось, что, возможно, autolayout не был запущен с помощью setstatusbarorientation, поэтому я попытался добавить этот код после, безрезультатно:</p><pre><code> [super updateviewconstraints]; [self.view updateconstraints]; </code></pre><p>я понимаю, что apple хочет оставить ориентацию устройства в руках пользователя. тем не менее, я хотел бы иметь возможность поддерживать ландшафтный режим, когда не в режиме «один на один». </p><p>я что-то упускаю, чтобы заставить меня изменить ориентацию?</p>

<p>для ios 7 и 8:</p><p>objective-c:</p><pre><code>nsnumber *value = [nsnumber numberwithint:uiinterfaceorientationlandscapeleft]; [[uidevice currentdevice] setvalue:value forkey:@"orientation"]; </code></pre><p>свифт 3+:</p><pre><code>let value = uiinterfaceorientation.landscapeleft.rawvalue uidevice.current.setvalue(value, forkey: "orientation") </code></pre><p>я называю это в <code>- viewdidappear:</code>.</p>

<p>использовать этот. идеальное решение проблемы ориентации. ios7 и ранее</p><pre><code>[[uidevice currentdevice] setvalue: [nsnumber numberwithinteger: uiinterfaceorientationportrait] forkey:@"orientation"]; </code></pre>

<p>вам нужно позвонить <a href="https://developer.apple.com/library/ios/documentation/uikit/reference/uiviewcontroller\_class/reference/reference.html#//apple\_ref/occ/clm/uiviewcontroller/attemptrotationtodeviceorientation"><code>attemptrotationtodeviceorientation (uiviewcontroller)</code></a> , чтобы система вызывала ваш <code>supportedinterfaceorientations</code>, когда условие изменилось.</p>

<pre><code>nsnumber *value = [nsnumber numberwithint:uiinterfaceorientationlandscapeleft]; [[uidevice currentdevice] setvalue:value forkey:@"orientation"]; </code></pre><p>работает, но вы должны вернуть shouldautorotate с yes в вашем контроллере представления</p><pre><code>- (bool)shouldautorotate { return self.shouldautorotate; } </code></pre><p>но если вы сделаете это, ваш vc будет автоматически вращаться, если пользователь поворачивает устройство ... , поэтому я изменил его на:</p><pre><code>@property (nonatomic, assign) bool shouldautorotate; - (bool)shouldautorotate { return self.shouldautorotate; } </code></pre><p>и я звоню </p><pre><code>- (void)swithinterfaceorientation:(uiinterfaceorientation)orientation { self.rootvc.shouldautorotate = yes; nsnumber *value = [nsnumber numberwithint: orientation]; [[uidevice currentdevice] setvalue:value forkey:@"orientation"]; } </code></pre><p>принудительно установить новую ориентацию с помощью нажатия кнопки . чтобы установить флажок shouldautorotate в no, я добавил в свой rootvc</p><pre><code>- (void)didrotatefrominterfaceorientation:(uiinterfaceorientation)frominterfaceorientation { self.shouldautorotate = no; } </code></pre><p>ps: этот обходной путь работает и во всех симуляторах.</p>

<p>это работает для меня <code>xcode</code> 6 и 5.</p><pre><code>- (bool)shouldautorotate { return yes; } - (nsuinteger)supportedinterfaceorientations { return (uiinterfaceorientationmaskportrait); } </code></pre>

<p>единственный способ, который сработал для меня, представляет фиктивный контроллер модального вида.</p><pre><code>uiviewcontroller* dummyvc = [[uiviewcontroller alloc] init]; dummyvc.view = [[uiview alloc] init]; [self presentmodalviewcontroller:dummyvc animated:no]; [self dismissmodalviewcontrolleranimated:no]; </code></pre><p>ваш vc будет запрошен для обновления ориентации интерфейса, когда контроллер модального вида отклонен.</p><p>любопытно, что uinavigationcontroller делает именно это при нажатии/выталкивании дочерних контроллеров представления с различными поддерживаемыми ориентациями интерфейса (протестировано на ios 6.1, 7.0).</p>

<p>это решение позволяет принудительно задать определенную ориентацию интерфейса, временно переопределив значение <code>uidevice.current.orientation</code> и затем попросив систему повернуть интерфейс, чтобы он соответствовал повороту устройства:</p><p><strong>важно: это взлом, и он может перестать работать в любой момент</strong></p><p>добавьте следующее в корневой контроллер вашего приложения:</p><pre><code>class rootviewcontroller : uiviewcontroller { private var \_interfaceorientation: uiinterfaceorientation = .portrait override var supportedinterfaceorientations: uiinterfaceorientationmask { return uiinterfaceorientationmask(from: \_interfaceorientation) } override var preferredinterfaceorientationforpresentation: uiinterfaceorientation { return \_interfaceorientation } override func viewdidload() { super.viewdidload() // register for notifications notificationcenter.default.addobserver(self, selector: #selector(rootviewcontroller.handleinterfaceorientationchangerequestednotification(\_:)), name: .interfaceorientationchangerequested, object: nil) } deinit { notificationcenter.default.removeobserver(self) } func handleinterfaceorientationchangerequestednotification(\_ notification: notification) { guard let interfaceorientation = notification.object as? uiinterfaceorientation else { return } \_interfaceorientation = interfaceorientation // set device orientation // important: // • passing a uideviceorientation here doesn't work, but passing a uiinterfaceorientation does // • this is a hack, and could stop working at any moment uidevice.current.setvalue(interfaceorientation.rawvalue, forkey: "orientation") // rotate the interface to the device orientation we just set uiviewcontroller.attemptrotationtodeviceorientation() } } private extension uiinterfaceorientationmask { init(from interfaceorientation: uiinterfaceorientation) { switch interfaceorientation { case .portrait: self = .portrait case .landscapeleft: self = .landscapeleft case .landscaperight: self = .landscaperight case .portraitupsidedown: self = .portraitupsidedown case .unknown: self = .portrait } } } extension notification.name { static let interfaceorientationchangerequested = notification.name(rawvalue: "interfaceorientationchangerequested") } </code></pre><p>убедитесь, что все ориентации интерфейса проверены в разделе «информация о развертывании»:</p><p> <a href="https://i.stack.imgur.com/ftsr9.png"> <img src="https://i.stack.imgur.com/ftsr9.png" alt="interface orientations"> </a> </p><p>запросите изменения ориентации интерфейса там, где они вам нужны:</p><pre><code>notificationcenter.default.post(name: .interfaceorientationchangerequested, object: uiinterfaceorientation.landscaperight) </code></pre>

<ol> <li><p>добавьте это утверждение в <code>appdelegate.h</code></p> <pre><code>//whether to allow cross screen marker @property (nonatomic, assign) allowrotation bool; </code></pre></li> <li><p>запишите этот раздел кода в <code>appdelegate.m</code></p> <pre><code>- (uiinterfaceorientationmask) application: (uiapplication *) supportedinterfaceorientationsforwindow: application (uiwindow *) window { if (self.allowrotation) { uiinterfaceorientationmaskall return; } uiinterfaceorientationmaskportrait return; } </code></pre></li> <li><p>измените свойство <code>allowrotation</code> приложения делегата</p></li> </ol>

<p>если у вас есть uiviewcontroller, который должен оставаться в портретном режиме, просто добавьте это переопределение, и все готово.</p><pre><code>override func supportedinterfaceorientations() -> uiinterfaceorientationmask { return uiinterfaceorientationmask.portrait } </code></pre><p>самое приятное, что при отображении этого вида анимация отсутствует, просто он уже в правильной ориентации.</p>

<p>если вы хотите заблокировать основной вид вашего приложения для портрета, но хотите открыть всплывающие виды в альбомной ориентации, и вы используете tabbarcontroller в качестве rootviewcontroller, как и я, вы можете использовать этот код в своем appdelegate.</p><p>appdelegate.h</p><pre><code>@interface appdelegate : uiresponder <uiapplicationdelegate, uitabbarcontrollerdelegate> @property (strong, nonatomic) uiwindow *window; @property (strong, nonatomic) uitabbarcontroller *tabbarcontroller; @end </code></pre><p>appdelegate.m</p><pre><code>- (bool)application:(uiapplication *)application didfinishlaunchingwithoptions:(nsdictionary *)launchoptions { self.window = [[uiwindow alloc] initwithframe:[[uiscreen mainscreen] bounds]]; // create a tab bar and set it as root view for the application self.tabbarcontroller = [[uitabbarcontroller alloc] init]; self.tabbarcontroller.delegate = self; self.window.rootviewcontroller = self.tabbarcontroller; ... } - (nsuinteger)tabbarcontrollersupportedinterfaceorientations:(uitabbarcontroller *)tabbarcontroller { return uiinterfaceorientationmaskportrait; } - (uiinterfaceorientation)tabbarcontrollerpreferredinterfaceorientationforpresentation:(uitabbarcontroller *)tabbarcontroller { return uiinterfaceorientationportrait; } </code></pre><p>это работает очень хорошо.</p><p>в вашем viewcontroller вы хотите быть представленными в альбомной ориентации, вы просто используете следующее:</p><pre><code>- (nsuinteger)supportedinterfaceorientations { return uiinterfaceorientationmasklandscape; } - (bool)shouldautorotate { return yes; } </code></pre>

<p>базовый uinavigationcontroller должен иметь обратный вызов ниже, чтобы дочерние элементы могли решить, какую ориентацию они хотят.</p><pre><code>-(nsuinteger)supportedinterfaceorientations { uiviewcontroller *topvc = self.topviewcontroller; return topvc.supportedinterfaceorientations; } -(bool)shouldautorotate { uiviewcontroller *topvc = self.topviewcontroller; return [topvc shouldautorotate]; } </code></pre>

<p>вот пример полной работы для ios 7, 8, 9, 10, как изменить ориентацию приложения на его текущую противоположность</p><p><strong> objective-c </strong></p><pre><code>- (void)fliporientation { nsnumber *value; uiinterfaceorientation currentorientation = [[uiapplication sharedapplication] statusbarorientation]; if(uiinterfaceorientationisportrait(currentorientation)) { if(currentorientation == uiinterfaceorientationportrait) { value = [nsnumber numberwithint:uiinterfaceorientationportraitupsidedown]; } else //if(currentorientation == uiinterfaceorientationportraitupsidedown) { value = [nsnumber numberwithint:uiinterfaceorientationportrait]; } } else { if(currentorientation == uiinterfaceorientationlandscaperight) { value = [nsnumber numberwithint:uiinterfaceorientationlandscapeleft]; } else //if(currentorientation == uiinterfaceorientationlandscapeleft) { value = [nsnumber numberwithint:uiinterfaceorientationlandscaperight]; } } [[uidevice currentdevice] setvalue:value forkey:@"orientation"]; [uiviewcontroller attemptrotationtodeviceorientation]; } </code></pre><p><strong> swift 3 </strong></p><pre><code>func fliporientation() -> void { let currentorientation : uiinterfaceorientation = uiapplication.shared.statusbarorientation var value : int = 0; if(uiinterfaceorientationisportrait(currentorientation)) { if(currentorientation == uiinterfaceorientation.portrait) { value = uiinterfaceorientation.portraitupsidedown.rawvalue } else //if(currentorientation == uiinterfaceorientation.portraitupsidedown) { value = uiinterfaceorientation.portrait.rawvalue } } else { if(currentorientation == uiinterfaceorientation.landscaperight) { value = uiinterfaceorientation.landscapeleft.rawvalue } else //if(currentorientation == uiinterfaceorientation.landscapeleft) { value = uiinterfaceorientation.landscaperight.rawvalue } } uidevice.current.setvalue(value, forkey: "orientation") uiviewcontroller.attemptrotationtodeviceorientation() } </code></pre>

<p>у меня была похожая проблема, чем у вас. мне нужно заблокировать ориентацию устройства для некоторых экранов (например, логин) и разрешить поворот на других.</p><p>после нескольких изменений и следующих ответов я сделал это:</p><ul> <li>включение всех ориентаций в info.plist проекта.</li> </ul><p> <a href="https://i.stack.imgur.com/rqhmm.png"> <img src="https://i.stack.imgur.com/rqhmm.png" alt="enter image description here"> </a> </p><ul> <li>отключение ориентации в тех viewcontrollers, где мне нужно, чтобы устройство не вращалось, как на экране входа в моем случае. мне нужно переопределить метод <code>shouldautorotate</code> в этом vc:</li> </ul><p><code>-(bool)shouldautorotate{ return no; }</code></p><p>надеюсь, это сработает для вас.</p>

<p>если вы хотите только портретный режим, в ios 9 (xcode 7) вы можете: <br></p><ul> <li>переход к info.plist</li> <li>выберите пункт «поддерживаемые ориентации интерфейса»</li> <li>удалить "пейзаж (левая кнопка домой)" и "пейзаж (правая кнопка домой)"</li> </ul><p> <a href="https://i.stack.imgur.com/6yiqp.png"> <img src="https://i.stack.imgur.com/6yiqp.png" alt="enter image description here"> </a> </p>

<p>это сработало у меня отлично ....</p><pre><code>nsnumber *value = [nsnumber numberwithint:uideviceorientationportrait]; [[uidevice currentdevice] setvalue:value forkey:@"orientation"]; </code></pre>

<p>для таких, как я, которые боролись за то, чтобы @sunny shah принял ответ на работу на ipad. вам необходимо установить флажок «требуется полный экран» в настройках проекта. обратите внимание, что это помешает вашему приложению работать в многозадачном режиме, который может быть или не быть приемлемым.</p><p> <a href="https://i.stack.imgur.com/58ksj.png"> <img src="https://i.stack.imgur.com/58ksj.png" alt="enter image description here"> </a> </p>

<p>попробуйте это вместе с вашим кодом.<br/></p><pre><code>-(bool)shouldautorotatetointerfaceorientation:(uiinterfaceorientation)interfaceorientation -(void)willrotatetointerfaceorientation:(uiinterfaceorientation)tointerfaceorientation duration:(nstimeinterval)duration </code></pre><p>после того, как пользователь выберет любую опцию, затем вызовите этот метод, потому что пользователь может быть в ландшафтном режиме, а затем он может установить только портретный режим в том же контроллере вида, поэтому автоматически вид должен быть переведен в портретный режим, поэтому в этой кнопке acton вызовите эту</p><pre><code>-(void)willrotatetointerfaceorientation:(uiinterfaceorientation)tointerfaceorientation duration:(nstimeinterval)duration </code></pre>