9

モーダルに表示する必要のあるビューが2つあります。次のように、閉じて連続して表示すると、これは機能しません。

[rootController dismissModalViewControllerAnimated: YES];
[rootController presentModalViewController: psvc animated: YES];

2番目のモーダルビューは単に表示されません。

私はこのような修正を見てきました:

[rootController dismissModalViewControllerAnimated: YES];
[[UIApplication sharedApplication] beginIgnoringInteractionEvents];
[self performSelector: @selector(seekModal) withObject: nil afterDelay: 0.5];
[[UIApplication sharedApplication] endIgnoringInteractionEvents];

問題は、これが常に機能するとは限らないことです(必要な遅延が優れている場合もあります)。

別の可能な修正は、アニメーションを削除することです。

[rootController dismissModalViewControllerAnimated: NO];
[rootController presentModalViewController: psvc animated: YES];

しかし、最初のモーダルが邪魔にならないように感じ続けるために、私は本当にアニメーションを維持したいと思います。助言がありますか?

4

7 に答える 7

17

編集: iOS5 +でこれを行うための「正しい」メカニズムは、– dismissViewControllerAnimated:completion:メソッドを使用し、完了ブロックからシーケンシャルビューコントローラーを提示することです。


モーダルで表示されているビューコントローラのviewDidDisappear:animated:メソッドは、modal-dismissal-animationが完了すると呼び出されます。AFIKこれは、後続のpresentModalViewController:animated:呼び出しを開始するためにフックできる唯一の場所です。

モーダルビューコントローラーを提示するために使用するクラスがあり、却下が完了すると、提示するビューコントローラーへのコールバックを介して探しているロジックを実装します。このクラスを使用するには、インスタンスを割り当て/初期化し、通常のpresentViewController:animated:呼び出しを使用して提示します。表示しているViewControllerに次のメソッドを実装します。

- (void) modalViewControllerDidDismiss:(UIViewController *)modalViewController

これは、モーダルビューコントローラーがなくなるとすぐに呼び出され、この時点で新しいモーダルビューコントローラーを提示できます。

また、このクラスはUINavigationControllerの特殊化であるため、navigationBarのオン/オフを自由に構成できます。このクラスには、必要に応じて、却下ボタンを表示するロジックも組み込まれています。

クラスの定義は次のとおりです。

@protocol TSModalViewControllerDelegate

- (void) modalViewControllerDidDismiss: (UIViewController*) modalViewController;

@end

@interface TSModalViewController : UINavigationController 
{
    UIViewController*   _originalParentViewController;
}
@property BOOL dismissButtonHidden;

- (id) initWithViewController: (UIViewController*) vc;
- (id) initWithClass: (Class) c;
- (id) initWithClass: (Class) c nibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil;

@end

そしてクラスの実装:

@implementation TSModalViewController
@synthesize dismissButtonHidden;

- (id) initWithViewController: (UIViewController *)vc
{
    return [super initWithRootViewController: vc];
}

- (id) initWithClass:(Class)c
{
    UIViewController* vc = [[[c alloc] init] autorelease];
    return [self initWithViewController: vc];
}

- (id) initWithClass: (Class) c nibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    UIViewController* vc = [[[c alloc] initWithNibName:nibNameOrNil bundle:nibBundleOrNil] autorelease];
    return [self initWithViewController: vc];
}

- (void) viewDidAppear: (BOOL) animated
{
    [super viewDidAppear: animated];

    [_originalParentViewController release];
    _originalParentViewController = [self.parentViewController retain];

    if (!self.dismissButtonHidden)
    {
        UIBarButtonItem* dismissButton = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem: UIBarButtonSystemItemStop
                                                                                        target: self 
                                                                                        action: @selector(onDismiss:)] autorelease];

        UIViewController* rootViewController = [self.viewControllers objectAtIndex:0];

        rootViewController.navigationItem.leftBarButtonItem = dismissButton;
        self.navigationBarHidden = NO;
    }   
}

- (void) viewDidDisappear:(BOOL)animated
{
    [super viewDidDisappear: animated];
    if ( [_originalParentViewController respondsToSelector: @selector(modalViewControllerDidDismiss:)] )
    {
        [_originalParentViewController performSelector: @selector(modalViewControllerDidDismiss:) withObject: self];
    }
}

- (void) dismissModalViewControllerAnimated:(BOOL)animated
{
    return [self.parentViewController dismissModalViewControllerAnimated: animated];
}

- (void) onDismiss: (id) sender
{
    [self.parentViewController dismissModalViewControllerAnimated: YES];
}

- (void) didReceiveMemoryWarning 
{
    [super didReceiveMemoryWarning];
}

- (void) viewDidUnload 
{
    [super viewDidUnload];
}

- (void)dealloc 
{
    [_originalParentViewController release];
    [super dealloc];
}

@end

そして、これがあなたがそれを使うことができる方法です(いくつかの通常のViewControllerのコンテキストで):

- (void) onShowIt:(id)sender
{
    TSModalViewController* mvc = [[[TSModalViewController alloc] initWithClass: [MyModalViewController class] nibName: @"MyModalViewController" bundle:nil] autorelease];
    mvc.dismissButtonHidden = YES;  // set to no if you don't want an "automatic" close button

    [self presentModalViewController: mvc animated: YES];
}

そして、これが却下コールバックメソッドです。これは新しいモーダルビューコントローラーを提供します。

- (void) modalViewControllerDidDismiss:(UIViewController *)modalViewController
{
    MyModalViewController* vc = [[[MyModalViewController alloc] initWithNibName: @"MyModalViewController" bundle:nil] autorelease];
    vc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;

    TSModalViewController* mvc = [[[TSModalViewController alloc] initWithViewController: vc] autorelease];

    [self presentModalViewController: mvc animated: YES];
}
于 2010-11-22T17:18:16.943 に答える
0

あなたの問題は「モーダルビュー内にモーダルビューを表示する」に関連していますか?私はこれについての答えをここに投稿しました: 別のモーダルビュー内のiPhoneモーダルビュー?

于 2010-11-20T21:17:35.243 に答える
0
// present modal view inside another presented modal view

    FirstViewController *firstVC = [[FirstViewController alloc] initWithNibName:@"FirstViewController" bundle:nil];
    UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController: firstVC];

    // Note: you can use your viewcontroller instead self.window.rootViewController

    [self.window.rootViewController presentViewController:navController animated:YES completion:^{
                //code...
                    SecondViewController *secondVC = [[SecondViewController alloc] initWithNibName:@"SecondViewController" bundle:nil];

                    [navController presentViewController: secondVC animated:YES completion:nil];

                }
            }];
于 2013-03-14T06:13:09.207 に答える
0

rootControllerは、viewDidAppear:を受信するため、その上にある最後のモーダルビューコントローラーがいつ消えたかを知ることができます。後続のViewControllerのpresentModalViewController:をそれにリンクしてみましたか?

于 2010-10-13T00:42:36.660 に答える
0

複数のビューアニメーションを本当に連鎖させたい場合は、実際にはアニメーションロジックを自分で処理することをお勧めします。それほどトリッキーではないので、ビューの表示方法をきめ細かく制御できます。私はちょうどここに別の質問のために似たようなものを書きました:

iOS-モーダルビューコントローラーのサイズをどのように制御しますか?

ビューをオンにアニメーション化し、ビューをオフにアニメーション化することができます。animationDidStopセレクターが呼び出されると、2番目のビューがオンにアニメーション化されます。これの良い部分は、ビューの不透明度とアニメーションの方向を操作したり、ビューをいつ表示するかを正確に決定したりできることです。たとえば、最初のビューがスライドして離れるときに、2番目のビューを最初のビューの上にスライドさせることができます。最初のものがアニメーションを完了するのを待つ必要はありません。

于 2010-11-20T15:09:01.893 に答える
0

このようなもの(それらがすべて親ビューの等しい子である場合)について私が見つけた最善の解決策は、ページングを有効にしてUIScrollViewにビューをパッチすることです(下部にページコントロールを追加して、明確にし、ナビゲーションすることができます)次に、コントローラーのビューが画面に表示されたらページビューに追加し、画面から外れたときに削除します。

コントローラがこれが呼び出されることに依存している場合は、-viewWillAppearと-viewWillDisappearをダミーで呼び出す必要がある場合もあります。すべてをコーディングするとちょっとハックっぽく感じますが、一度動作させるとスムーズで自然に見え、1つのビューをアニメーション化してから、次のビューを一度にアニメーション化することに関連する待機はありません。なくなっている。

于 2010-11-21T17:03:46.760 に答える
0

モーダルビューの-viewDidDissapearを使用して、表示しているViewControllerのメソッドを呼び出すのは非常にうまくいきます。1つの利点は、モーダルビューコントローラでの割り当て解除を遅らせることができることです。私ができる改善点を投稿してください。このプロトコルを作成するための私のインスピレーションは、UIViewControllerへのiOS 5の「dismissViewControllerAnimated:completion:」の追加から来ました。iOS4.3でこの機能が欲しかった。


PresentorDelegateProtocol.h

@protocol PresentorDelegateProtocol <NSObject>
@optional

/* 

Extra protocol methods defined in protocol for flexibility.  
Main methods are:
- (void)dismissPresentingModalViewController:(id)modalView animated:(BOOL)animated; 
- (void)modalViewDissapeared:(id)modalView;  //used in modal view's -viewDidDissapear

*/

- (void)dismissPresentingModalViewController:(id)modalView animated:(BOOL)animated;
- (void)modalViewDissapeared:(id)modalView; 

// use the block in this method send messages to save state, etc.  This is the one I like to use.
- (void)dismissPresentingModalViewController:(id)modalView animated:(BOOL)animated withBlock:(void(^)())block;

// use in other classes that are not controlling dismissal of the modal view
- (void)executeBlockOnModalDissapearance: (void(^)())block;

@end

PresentingViewController.h

#import "PresentorDelegateProtocol.h"
@interface PresentingViewController : UIViewController <PresentorDelegateProtocol>
- (void)showModalVC;
@end

ModalViewController.h

#import "PresentorDelegateProtocol.h"
@interface ModalViewController : UIViewController
@property (nonatomic, assign) id <PresentorDelegateProtocol> presentorDelegate;
- (void)close;
@end

PresentingViewController.m

#import "PresentingViewController.h"
#import "ModalViewController.h"
@implementation PresentingModalViewController
- (void)showModalVC
{
    ModalViewController *modalVC = [[ModalViewController alloc] initWithNibName:@"ModalViewController" bundle:nil];
    modalVC.presentorDelegate = self;
    [self presentModalViewController:modalVC animated:YES];
}
- (void)dismissPresentingModalViewController:(id)modalView animated:(BOOL)animated
{
    if ([modalView isKindOfClass:[ModalViewController class]]) {
        NSLog(@"Can invoke based on class"); 
    }
    [self dismissModalViewControllerAnimated:animated];    
}
- (void)dismissPresentingModalViewController:(id)modalView animated:(BOOL)animated withBlock:(void(^)())block
{
    block();  
    /* execute block before or after calling to dismiss modal view */
    [self dismissPresentingModalViewController:modalView animated:animated];
    //block();
}
- (void)modalViewDissapeared:(id)modalView
{
    if ([modalView isKindOfClass:[ModalViewController class]]) {
        NSLog(@"Do stuff based on class.");
    }
}
- (void)executeBlockOnModalDissapearance: (void(^)())block
{
    block();
    NSLog(@"This delay's dealloc on modal view until block completes");
}
@end

ModalViewController.m

#import "ModalViewController.h"
@implementation ModalViewController
@synthesize presentorDelegate;

- (void)close
{
    if (1 == 0 /*need to do something before dealloc*/){
        [self.presentorDelegate dismissPresentingModalViewController:self animated:YES withBlock:^{
            NSLog(@"Do stuff with block.  Save, animate, etc");
        }];

    } else {
        [self.presentorDelegate dismissPresentingModalViewController:self animated:YES];
    }
}

- (void)viewDidDisappear:(BOOL)animated
{
    if (1 == 0 /*stuff to do*/){
        [self.presentorDelegate executeBlockOnModalDissapearance:^{
        // do stuff before modal view is deallocated
        }];
    }
    [self.presentorDelegate modalViewDissapeared:self];

    presentorDelegate = nil;
    [super viewDidDisappear:animated];
}
@end;
于 2012-02-11T22:59:16.157 に答える