Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
65
Help us understand the problem. What is going on with this article?
@edo_m18

[Objective-C] UIViewControllerの回転周りのまとめ

More than 5 years have passed since last update.

コードによる回転の制御

どうもiOS6あたりから制御方法が変わったらしい。
それまではshouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientationメソッドで制御していたが、今はふたつのメソッドで制御するぽい。

//ここで回転していいかの判別をする
- (BOOL)shouldAutorotate
{
    if (/* なにがしかの回転していいかの判定処理 */) {
        return YES;
    }

    return NO;
}

//どの方向に回転していいかを返す(例ではすべての方向に回転OK)
- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskAll;
}

ちなみに回転のタイミングでなにかしたい場合。

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration
{
    //回転時に処理したい内容
}

shouldAutorotateが呼ばれない場合

こちらの記事に書いてありました。
記事では、self.window.rootViewControllerに、自分で作成したUINavigationControllerを設定していると動作しないようです。
回転をコードから制御したい場合は、UINavigationControllerのサブクラスを作り、そちらに上記デリゲートメソッドを実装することで制御可能なようです。

サンプルコード

@interface HogeNavigationController : UINavigationController

@end

/////////////

@implementation HogeNavigationController

- (BOOL)shouldAutorotate
{
    return YES; // or NO
}

- (NSUInteger)supportedInterfaceOrientations
{
    // ポートレイトだけ許可
    return UIInterfaceOrientationMaskPortrait;
}

@end

UINavigationControllerのカテゴリで対処する

ただ、回転のためだけに継承するのもあれなので、ということでカテゴリで対応する方法のほうがスマートかもしれません。

【UINavigationControllerの子ViewControllerにも回転イベントを伝える】
これには、カテゴリによる拡張を使うことでシンプルに解決できます。

@implementation UINavigationController (Rotation)

- (NSUInteger)supportedInterfaceOrientations
{
    return [self.viewControllers.lastObject supportedInterfaceOrientations];
}

- (BOOL)shouldAutorotate
{
    return [self.viewControllers.lastObject shouldAutorotate];
}
@end
参考
解説

UINavigationControllerのカテゴリで回転に関するdelegateをオーバーライドします。

その上で、自身のviewControllersの最後のViewControllerにも回転系のメッセージを送ります。
理由としては、( 上記リンクの下の記事を見てもらうと分かりますが )仕様的にrootViewControllerにUINavigationControllerが設定されている場合、その子ViewControllerには回転系のメッセージは送られないようです。
そのために、カテゴリで拡張し、最後ViewControllerの(つまり現在表示されてる)ViewControllerにメッセージを送っている、というわけです。


イベントの発生順

  1. shouldAutorote
  2. supportedInterfaceOrientations
  3. willRotateToInterfaceOrientaion:duration:

起動時の取得

起動時の画面の向きを取得するには、UIViewControllerのプロパティinterfaceOrientationを利用すればいいようです。

UIInterfaceOrientation direction = self.interfaceOrientation;
if(direction == UIInterfaceOrientationPortrait){
    // 縦(ホームボタンが下)
}
else if(direction == UIInterfaceOrientationPortraitUpsideDown){
    // 縦(ホームボタンが上)
}
else if(direction == UIInterfaceOrientationLandscapeLeft){
    // 横(ホームボタンが左)
}
else if(direction == UIInterfaceOrientationLandscapeRight){
    // 横(ホームボタン右)
}
65
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
edo_m18
現在はUnity ARエンジニア。 主にARのコンテンツ制作をしています。 最近は機械学習にも興味が出て勉強中です。 Unityに関するブログは別で書いています↓ https://edom18.hateblo.jp/
unity-game-dev-guild
趣味・仕事問わずUnityでゲームを作っている開発者のみで構成されるオンラインコミュニティです。Unityでゲームを開発・運用するにあたって必要なあらゆる知見を共有することを目的とします。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
65
Help us understand the problem. What is going on with this article?