21748


現在`UITraitCollection`を使ってiPhoneとiPadを区別しようとしているのですが、イマイチ`UITraitCollection`の使い方がわかりません。  
まず以下のようにコードを書いてデバイスの回転時にRegularかCompactかを検知してそれに沿った処理を記述するようにしました。

[code]

    - (void)willTransitionToTraitCollection:(UITraitCollection *)newCollection withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
        if (newCollection.horizontalSizeClass == UIUserInterfaceSizeClassRegular) {
            NSLog(@"Regular");
    
            UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
            ViewController *VC = [storyboard instantiateViewControllerWithIdentifier:@"ViewController"];
            UINavigationController *navVC = [[UINavigationController alloc] initWithRootViewController:VC];
            [self.splitViewController showDetailViewController:navVC sender:self];
    
        } else {
            NSLog(@"Compact");
    
        }
        [super willTransitionToTraitCollection:newCollection withTransitionCoordinator:coordinator];
    }
    
[/code]

しかし上記のコードだとiPhone
6plusを縦画面から横画面にした時にアプリが落ちます。無限ループのような形で落ちます。なぜアプリが落ちてしまうのでしょうか？  
また、showDetailViewControllerに関するロジックを除けてログだけを取るようにすると、なぜか画面を一回転させただけでも、「Compact
Regular Compact」というようにログに表示されます。  
そして、`viewDidLoad`で下記のコードをiPadで実行すると、「Regular Compact」とログが表示されます。

[code]

    if ([self.traitCollection containsTraitsInCollection: [UITraitCollection traitCollectionWithHorizontalSizeClass: UIUserInterfaceSizeClassRegular]]) {
        NSLog(@"Regular");
    
    } else {
        NSLog(@"Compact") 
    }
    
[/code]

なぜ二回も呼ばれているのか調べると、`willTransitionToTraitCollection`が呼ばれていたようです。画面が回転してないにもかかわらず。  
このように、全くUITraitCollectionを使用してiPhoneとiPadを区別することができてません。  
なぜ上記のような複数回メソッドが呼ばれたり、アプリが無限ループになって落ちたりする挙動になってしまっているのでしょうか？  
色々と調べてみても`UITraitCollection`の具体的な使い方に関する記事が少なく、これ以上どうすればいいかわかりません。  
どなたかわかる方がいれば教えていただきたいです。宜しくお願いします。


CC BY-SA 3.0
2016-02-01T09:43:58.837
21574
2016-02-05T11:04:33.613
5210
question
ios objective-c uisplitviewcontroller
UITraitCollectionの使い方について


質問が多数含まれているので、順番に解答します。

また、質問に必要な情報が含まれていないので、以下の仮定の下に解答をしています。

  * Master-Detail Applicationのひな形からプロジェクトを作成
  * 質問文にあるwillTransitionToTraitCollectionはMasterViewControllerに追加

## iPhone 6 Plusを回転したときに落ちる

willTransitionToTraitCollectionの中でshowDetailViewControllerを呼び出しているのが原因です。

showDetailViewControllerを呼び出した結果、UISplitViewControllerにwillTransitionToTraitCollectionが発生し、UISplitViewControllerに管理されているMasterViewControllerにもそれが派生するので無限ループになっているようです。

無限ループになった結果、最終的にスタックオーバーフローでアプリが落ちます。

## iPhone 6 Plusを回転したときに『Compact Regular Compact』と表示される

おそらく、UISplitViewControllerの仕様（副作用？）だと思われます。

UISplitViewControllerを使っていないプロジェクトであれば、回転後のTraitに合わせて、willTransitionToTraitCollectionは1回しか呼び出されません。

1回目のCompactは謎です。2回目のRegularはiPhone 6
Plusを横にした結果。3回目のCompactはUISplitViewControllerでMasterViewControllerが狭まった結果のように思えます。

## iPadで実行すると『Regular Compact』と表示される

これも、UISplitViewControllerの仕様だと思われます。

viewDidLoadとwillTransitionToTraitCollectionで同じ単語を出力しているのでわかりにくいですが、1回目のRegularはviewDidLoadに追加されたコードによる出力で、2回目のCompactはwillTransitionToTraitCollectionによるものです。

画面を回転させていないのに、willTransitionToTraitCollectionからCompactが出力される理由ですが、おそらく、UISplitViewControllerがDetailViewControllerを表示した結果だと思われます。

## iPhoneとiPadを区別する方法

UIDeviceのcurrentDeviceを使えば良いのではないでしょうか？


CC BY-SA 3.0
2016-02-05T11:04:33.613
21748
2016-02-05T11:04:33.613
7459
21574
answer