質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

1回答

3880閲覧

UINavigationControllerで管理されたViewControllerの中で特定のViewControllerだけ横向きにしたい

tama2015

総合スコア63

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

1クリップ

投稿2017/10/24 13:11

NavigationController配下の3つのコントローラーが有り
ViewControllerA
ViewControllerB
ViewControllerC

A -> B -> C
と遷移します。

Bだけ、横表示にして、他のAとCは縦で表示したいのですが
中々うまくいきません。Cから戻った時も、Bは横、Aは縦に
なってほしいです。

環境は、Xcode9.0.1 Swift3.0です。
NavigationController配下のviewcontrollerをひとつだけ
横表示にする方法をご存知の方がいらっしゃいましたら
ご教授頂けませんでしょうか?

よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

このorientationの話題なんだか情報まとまってない感のある話題ですよね。
それに某ネット通販サイトにある動画サービスをiPhoneで利用すると、動画が流れる時に強制的にlandscapeになるのが前から気になっていたのでちょっとやってみました。
残念ながらswift4なので(起動および動作確認済みですが)swift3で使えるかは謎です。

なので

###事前の情報共有

環境
Xcode 9.0.1
swift 4

swift4では

public var shouldAutorotate: Bool { get }

となっていますがネットの情報を調べていると

open func shouldAutorotate() -> Bool

ってなってたりしてるんですよね。なのでお手持ちのライブラリを確認して下の形ならこれから書くコードを修正するか、swift4で開発するかしてください。

命名ですがNCはNavigationController, VC1, VC2, VC3はそれぞれ一番目、二番目、三番目のViewControllerです。
またNC, VC1, VC2, VC3はそれぞれStorybordでCustom Classにするかいい具合にしてください。

以下は分かりにくい表現です。
デバイスの向き:iPhoneやiPad等実機(orシミュレータ)を持った時の向きです。縦向きはホームボタンが上下に、横向きはホームボタンが左右にきます。
landscape, portrait:ViewControllerの向きです。
これらは別々のものとして扱います。

###これからやることの流れ

  1. まずUINavigationControllerから各々のViewControlllerにorientationの制約を与えていきます。

例を挙げると.portraitの制約与えた時、デバイスを縦向きにしても横向きにしてもViewControllerはportraitの向きのままである、と言うことです。ViewControllerが表示された時に強制的に横向きにすると言うわけではありません。また、デバイスを縦向きのままVC1からVC2に画面遷移を行なってもVC2はportraitのままです。VC2に画面遷移後デバイスを横向きにするとVC2はlandscapeになります。

  1. なので次に各々のViewControllerが表示された時に(今回はviewDidAppear内で行います)強制的にViewControllerをlandscapeやportraitにします。

###コード
0. UINavigationControllerに制約を与えます。

swift

1 2import UIKit 3 4class NC: UINavigationController { 5 6 override func viewDidLoad() { 7 super.viewDidLoad() 8 } 9 10 override func didReceiveMemoryWarning() { 11 super.didReceiveMemoryWarning() 12 } 13 14    override public var supportedInterfaceOrientations: UIInterfaceOrientationMask { 15 guard let vc = visibleViewController else { 16 fatalError() 17 } 18 if vc is VC2 { 19 return .landscape 20 } else { 21 return .portrait 22 } 23 } 24 25 override public var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation { 26 guard let vc = visibleViewController else { 27 fatalError() 28 } 29 if vc is VC2 { 30 return .landscapeLeft 31 } else { 32 return .portrait 33 } 34 } 35 36} 37
  1. ViewControllerの向きを強制的に変えます。

swift

1class VC1: UIViewController { 2 3 override func viewDidLoad() { 4 super.viewDidLoad() 5 // Do any additional setup after loading the view, typically from a nib. 6 } 7 8 override func didReceiveMemoryWarning() { 9 super.didReceiveMemoryWarning() 10 // Dispose of any resources that can be recreated. 11 } 12 13 override func viewDidAppear(_ animated: Bool) { 14 super.viewDidAppear(animated) 15 let value = UIInterfaceOrientation.portrait.rawValue 16 UIDevice.current.setValue(value, forKey: "orientation") 17 } 18 19} 20 21class VC2: UIViewController { 22 23 override func viewDidLoad() { 24 super.viewDidLoad() 25 } 26 27 override func didReceiveMemoryWarning() { 28 super.didReceiveMemoryWarning() 29 } 30 31 override func viewDidAppear(_ animated: Bool) { 32 super.viewDidAppear(animated) 33 let value = UIInterfaceOrientation.landscapeLeft.rawValue 34 UIDevice.current.setValue(value, forKey: "orientation") 35 } 36 37} 38 39class VC3: UIViewController { 40 41 override func viewDidLoad() { 42 super.viewDidLoad() 43 44 // Do any additional setup after loading the view. 45 } 46 47 override func didReceiveMemoryWarning() { 48 super.didReceiveMemoryWarning() 49 // Dispose of any resources that can be recreated. 50 } 51 52 override func viewDidAppear(_ animated: Bool) { 53 super.viewDidAppear(animated) 54 let value = UIInterfaceOrientation.portrait.rawValue 55 UIDevice.current.setValue(value, forKey: "orientation") 56 } 57 58}

###動いてるとこ
orientation

###余談
Deployment Infoにあるdevice Orientationに全部チェックを入れても、逆に全部チェックを外しても動作しました。どういう流れになってるんでしょうかね。

投稿2017/10/27 18:59

編集2017/10/28 17:31
xAxis

総合スコア1349

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tama2015

2017/10/28 13:12

回答ありがとうございます。ちょうど、強制的に位置を制御する方法(下の方法)で 対処しておりました。 上の方法でも3で出来るかどうかを確認してみます。丁寧な回答誠にありがとうございました。
xAxis

2017/10/28 14:55

下に書いたコードだけだと強制的にlandscapeには出来てもデバイスを立てるとportraitになっちゃいませんか?上下両方のコードを書くとgif画像のようにデバイスを立てた状態でもlandscapeに出来る、ということです。よく分からなかったら言ってください。また回答修正します。
tama2015

2017/10/28 16:14

すいません。まず、私のコメントが間違いでした。UINavigationControllerのextensionに追加する形で、上のほうの supportedInterfaceOrientationsとpreferredInterfaceOrientationForPresentationも 実装していました。 swift3ですがほぼ同一のものだと思います。 (そろそろ、自己回答を書こうとしていた矢先でした。) あと、回答も上の方法だけで出来るという主張と勘違いしてました。
xAxis

2017/10/28 17:04

了解です。やはり自分の書き方にも誤解を生む要素があったと思うのでもう少々修正しておきます。自分は理解を優先してシンプルな構成にしますが、extensionで書くとよりswiftらしい(と言うらしい)と思います。なので自己解答されるのもありだと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問