これは iOS5 のバグだと思います。他のモーダルからモーダル ビュー コントローラを提示する実験をいくつか行ったところ、2 番目のモーダルが下の画面を暗くすることはないようです。相互に無限のモーダルを起動できるようにするテスト プロジェクトをセットアップしましたが、他のすべてのモーダルが期待どおりに暗くなったり、タッチをブロックしたりしないようです。
UIWindow サブビューの簡単な NSLog は、ドロップ シャドウが適切に追加されている一方で、dimmingView が適切に追加されていないことを示しています。私は自分の調光ビューを表示する方法に取り組んでいます。方法が見つかったら、この回答を更新します。
Window Subviews: (
"<UILayoutContainerView: 0xf63e3c0; frame = (0 0; 768 1024); transform = [0, 1, -1, 0, 0, 0]; autoresize = W+H; layer = <CALayer: 0xf645640>>",
"<UIDimmingView: 0xf683990; frame = (0 0; 768 1024); opaque = NO; layer = <CALayer: 0xf6836d0>>",
"<UIDropShadowView: 0xf683130; frame = (64 64; 640 896); transform = [0, 1, -1, 0, 0, 0]; autoresize = W+H; layer = <CALayer: 0xf6831c0>>",
"<UIDropShadowView: 0x292110; frame = (74 242; 620 540); transform = [0, 1, -1, 0, 0, 0]; autoresize = LM+RM+TM+BM; layer = <CALayer: 0x292150>>"
)
解決策 2:
アニメ調の最終的な解決策です。また、私は最初の解決策について考えなければなりませんでした。これは Apple を怒らせ、技術的に可能であり、UIDimmingView は文書化されておらず、私たちは「それに触れる」ため、拒否を引き起こします。ViewController に必要なアルファの背景色を持つ UIView を追加します。次に、モーダルを提示するときにそれをアニメーション化し、2 番目のモーダルのデリゲートが呼び出されたときにアニメーションを逆にします。私にはかなり良さそうです。たぶん、タイミングとアルファの微調整がちょうどいいものになるかもしれませんが、うまく機能し、見栄えがします。
- (void)viewDidLoad
{
dim = [[UIView alloc] init];
[dim setBackgroundColor:[UIColor colorWithWhite:0.0 alpha:0.35]];
[dim setAlpha:0.0];
[dim setUserInteractionEnabled:NO];
[self.view addSubview:dim];
}
- (void)presentModal
{
[self.view bringSubviewToFront:dim];
[dim setFrame:self.view.frame];
[UIView animateWithDuration:0.25 animations:^{
[dim setAlpha:1.0];
}];
}
- (void)modalDelegateFinished
{
[UIView animateWithDuration:0.25 animations:^{
[dim setAlpha:0.0];
}];
}
解決策 1:
これでうまくいきましたが、私が望むほどアニメーション化されていません。しかし、それはすでにそこにあるものを再利用するので、おそらくそれにはプラスがあります.
- (void)viewDidAppear:(BOOL)animated
{
// Add a gesture to dismiss the view if tapped outside.
UIGesture *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tappedOutsideView:)];
[gesture setNumberOfTapsRequired:1];
[gesture setCancelsTouchesInView:NO];
[self.view.window addGestureRecognizer:gesture];
// Move the dimmingview to just below the dropshadow.
UIView *dim = [self.view.window.subviews objectAtIndex:1];
[self.view.window insertSubview:dim atIndex:2];
}
- (void)tappedOutsideView:(UITapGestureRecognizer *)sender
{
if (sender.state == UIGestureRecognizerStateEnded) {
CGPoint location = [sender locationInView:nil];
if (![self.view pointInside:[self.view convertPoint:location fromView:self.view.window] withEvent:nil]) {
// remove the gesture on the window
[self.view.window removeGestureRecognizer:sender];
// Move the dimmingview back where it belongs
UIView *dim = [self.view.window.subviews objectAtIndex:2];
[self.view.window insertSubview:dim atIndex:1];
}
}
}
また、フェイルセーフとして、viewDidDisappear の同じものにおそらく良い考えです。私の完了ボタンは tappedOutside ビューを呼び出すので、ジェスチャーと dimmingView が常に正しく配置されていることがわかります。しかし、そのようにしなかった場合は、viewDidDisappear に入れることができます。
- (void)viewDidDisappear:(BOOL)animated
{
// remove the gesture on the window
for (UIGestureRecognizer *gesture in self.view.window.gestureRecognizers) {
[self.view.window removeGestureRecognizer:gesture];
}
// Move the dimmingview back where it belongs
UIView *dim = [self.view.window.subviews objectAtIndex:2];
[self.view.window insertSubview:dim atIndex:1];
}