

今、テザリング時のような見た目のビュー（ボタン）を設置してアクションさせるための機能を作成しています。

具体的には、とあるアクション時に、画面上部に44pxの高さのボタンを設置し、ショートカットとして使ってもらうことを想定したものです。

現在の実装は、AppDelegateが持っているkey windowを縮小し、上端に空きを作った上でそこにボタンを配置しています。  
iOS8では意図した通りに動作しているのですが、iOS6, 7で意図した挙動にならないときがあります。

意図した挙動にならないのは「モーダルビュー」を表示した時で、`presentViewController:animated:completion:`を実行したタイミングです。  
これを実行すると、（見た目には）上記でリサイズしたkey windowのサイズが元に戻り、その上でモーダルビューが表示されます。

結果として重ねたボタンの下にビューが潜り込んでしまう、というものです。  
この挙動について、なにか分かりますでしょうか？

[2015.02.04 追記]

コメント頂いたので再現する最小コードを載せます。  
再現手順は、

  1. 新規プロジェクト作成（Storyboard未使用）
  2. AppDelegateに以下コード追加
  3. 起動(Run)
  4. 画面中央あたりにある＋ボタン押下（UIWindowリサイズ）
  5. barButton（ブックマーク型）押下（modal view表示）
  6. 現象発生

となります。

[code]

    - (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        UIButton *button = [UIButton buttonWithType:UIButtonTypeContactAdd];
        button.frame = CGRectMake(50, 150, 100, 44);
        [button addTarget:self
                   action:@selector(tap:)
         forControlEvents:UIControlEventTouchUpInside];
    
    
        // ViewController
        self.viewController = [[UIViewController alloc] init];
        self.viewController.view.backgroundColor = UIColor.blueColor;
        self.viewController.definesPresentationContext = NO;
        [self.viewController.view addSubview:button];
    
        UIBarButtonItem *barButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemBookmarks
                                                                                   target:self
                                                                                   action:@selector(barBtnTap:)];
        self.viewController.navigationItem.rightBarButtonItem = barButton;
    
    
        // NavigationController
        UINavigationController *nv = [[UINavigationController alloc] initWithRootViewController:self.viewController];
    
        self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
        self.window.backgroundColor = UIColor.redColor;
        self.window.rootViewController = nv;
        [self.window makeKeyAndVisible];
    
        return YES;
    }
    
    - (void)barBtnTap:(id)sender
    {
        UIView *mark = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];
        mark.backgroundColor = UIColor.yellowColor;
        UIViewController *modal = [[UIViewController alloc] init];
        modal.view.backgroundColor = UIColor.grayColor;
        [modal.view addSubview:mark];
        [self.viewController presentViewController:modal
                                          animated:YES
                                        completion:nil];;
    }
    
    - (void)tap:(id)sender
    {
        self.backupFrame = self.window.frame;
        CGRect newFrame = self.window.frame;
    
        NSInteger pad = 60;
        newFrame.size.height -= pad;
        newFrame.origin.y    += pad;
    
        self.window.frame = newFrame;
    
        CGRect otherFrame = CGRectMake(0, 0, newFrame.size.width, pad);
        self.otherWindow = [[UIWindow alloc] initWithFrame:otherFrame];
        self.otherWindow.backgroundColor = UIColor.greenColor;
        [self.otherWindow makeKeyAndVisible];
    }
    
[/code]


CC BY-SA 3.0
2015-02-03T09:35:12.710
5850
2016-08-22T03:03:44.637
2015-02-04T01:31:09.123
100
100
question
ios objective-c iphone ios6
AppDelegateが持っているUIWindowのリサイズがモーダルビューを表示すると元に戻る


手元で確認したところ表示される `UIViewController` の `loadView` で作られた `view(0 0; 320 480)` が、
`viewWillLayoutSubviews` が呼び出されるタイミングでは `view(0 -60; 320 480)` となっておりました。  
そのため以下のように実装したところ想定通り動作することを確認しました。

[code]

    - (void)viewWillLayoutSubviews
    {
        // [UIApplication sharedApplication].keyWindow で目的の window がとれるように
        // [self.otherWindow makeKeyAndVisible]; の後に
        // [self.window makeKeyWindow]; しています。
        CGSize windowSize = [UIApplication sharedApplication].keyWindow.frame.size;
        self.view.frame = CGRectMake(0, 0, windowSize.width, windowSize.height);
        [super viewWillLayoutSubviews];
    }
    
[/code]

どのタイミングで `view.frame` が変更されるかの詳細は把握していないので、`viewWillLayoutSubviews`
ではなく別の場所が適切かもしれません。


CC BY-SA 3.0
2015-02-04T03:54:22.090
5914
2015-02-04T03:54:22.090
5106
5850
answer