ビューの外側をタップすると、モーダル ビュー コントローラーを閉じることができるメカニズムを設定しました。セットアップは次のとおりです。
- (void)viewDidAppear:(BOOL)animated
{
UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapBehind:)];
[recognizer setNumberOfTapsRequired:1];
recognizer.cancelsTouchesInView = NO; //So the user can still interact with controls in the modal view
[self.view.window addGestureRecognizer:recognizer];
}
- (void)handleTapBehind:(UITapGestureRecognizer *)sender
{
if (sender.state == UIGestureRecognizerStateEnded)
{
CGPoint location = [sender locationInView:nil]; //Passing nil gives us coordinates in the window
//Then we convert the tap's location into the local view's coordinate system, and test to see if it's in or outside. If outside, dismiss the view.
if (![self.view pointInside:[self.view convertPoint:location fromView:self.view.window] withEvent:nil])
{
[self dismissModalViewControllerAnimated:YES];
NSLog(@"There are %d Gesture Recognizers",[self.view.window gestureRecognizers].count);
[self.view.window removeGestureRecognizer:sender];
}
}
}
これは、単一のモーダル ビューを閉じる場合に驚くほど機能します。ここで、2 つのモーダル ビューがあるとします。1 つはルート ビュー コントローラー (ビュー A) 内から呼び出され、次に別のモーダルが最初のモーダル内から呼び出されます (ビュー B)。
このような種類:
ルート ビュー -> ビュー A -> ビュー B
タップしてビュー B を閉じると、すべて問題ありません。ただし、EXC_BAD_ACCESS
ビュー A を閉じようとするとエラーが発生します。ゾンビをオンにしたhandleTapBehind:
後、ビュー B が閉じられた後に閉じられてメモリが不足しているにもかかわらず、ビュー B にメッセージが送信されているようです。
私の質問は、ビュー B がまだメッセージを送信されているのはなぜですか? (handleTapBehind:
関連するウィンドウからジェスチャレコグナイザーが削除されていることを確認してください。)そして、ビューBがすでに閉じられた後にビューAに送信するにはどうすればよいですか。
PS。上記のコードは、ビュー A とビュー B の両方のコントローラー内に表示され、同一です。
編集
モーダル ビュー コントローラーを呼び出す方法は次のとおりです。このコードは、標準のビュー階層内にあるビュー コントローラー内にあります。
LBModalViewController *vc = [[LBModalViewController alloc] initWithNibName:@"LBModalViewController" bundle:nil];
[vc.myTableView setDataSource:vc];
[vc setDataArray:self.object.membersArray];
[vc setModalPresentationStyle:UIModalPresentationFormSheet];
[vc setModalTransitionStyle:UIModalTransitionStyleFlipHorizontal];
[vc.view setClipsToBounds:NO];
[self presentViewController:vc animated:YES completion:nil];
// This is a hack to modify the size of the presented view controller
CGPoint modalOrigin = vc.view.superview.bounds.origin;
[[vc.view superview] setBounds:CGRectMake(modalOrigin.x, modalOrigin.y, 425, 351)];
[vc.view setBounds:CGRectMake(modalOrigin.x, modalOrigin.y, 425, 351)];
それだけで、他のすべてはかなり標準的です。