0

presentModalViewControllerメソッドを使用して提示されたUIViewControllerの階層があります。

提示されたすべてのViewControllerをアレイに取り込むシングルトンがあります。

たとえば、コントローラーA、B、Cの順に提示しました。各コントローラーをインデックス0に挿入しました。

だから私は以下のような階層を持っています

C

B

A

これは私のシングルトンです

@implementation PresentHelper

- (id)init
{
    self = [super init];
    if (self) {
        self.viewControllers = [NSMutableArray new];
    }
    return self;
}

+ (PresentHelper *)sharedInstance
{
    static dispatch_once_t pred;
    static PresentHelper *sharedInstance = nil;
    dispatch_once(&pred, ^{
        sharedInstance = [[self alloc] init];
    });
    return sharedInstance;
}

- (void)backToViewControllerA
{
    for (UIViewController *controller in self.viewControllers) {
        [controller dismissModalViewControllerAnimated:NO];
    }
    [self.viewControllers removeAllObjects];
}

@end

UIViewControllerCI呼び出しbackToViewControllerAメソッド。

- viewDidLoadしたがって、このメソッドをデバッグしているときに、この行の後にメソッド(self.viewControllersの各コントローラーに対して)が呼び出されるのはなぜか[controller dismissModalViewControllerAnimated:NO];と思っていました。このように動作するはずはないのですが、動作します。

したがって、これはビューコントローラAに戻る方法の1つではないかもしれませんが、私の質問はいずれにせよviewDidLoadメソッドに関連しています。

また、これは私が各コントローラーを提示する方法の下の私のコードです。基本クラスとそれぞれがあります(A、B、Cコントローラーはそこから継承されます)。

- (void)presentModalViewController:(UIViewController *)modalViewController animated:(BOOL)animated
{
    PresentHelper *presentHelper = [PresentHelper sharedInstance];
    [presentHelper.viewControllers insertObject:modalViewController atIndex:0];
    [super presentModalViewController:modalViewController animated:animated];
}

また、このメッセージを受け取りました

NSArrayは列挙中に変更されました

ですから、却下した後、私は自分のオブジェクトを失い、おそらくこれが私の問題だと思います。

4

2 に答える 2

1

これは、シングルトンの適切な使用法ではないようです。

Aに戻るには、いくつかの方法があります。各コントローラーは、そのプロパティを通じて前のコントローラーへの参照を持っているため、追加のデリゲートメソッドやプロパティを作成する必要はありませんpresentingViewController。(言い換えると... iOS5 +の場合、組み込みのviewControllerプロパティを使用できますpresentingViewController)。iOS4.3との互換性を維持するには、プロパティを作成して基本クラスに配置します@interface

    @property (nonatomic, assign) UIViewController* presentingController;

また、ベースクラスインターフェイスで、メソッドを宣言します。

    - (void) dismissBackToA;

@implementation@synthesizeあなたのプロパティと定義dismissBackToA

 - (void) dismissBackToA
{
    if ([[self presentingController] respondsToSelector:@selector(dismissBackToA)]) {
           [[self presentingController] performSelector:@selector(dismissBackToA)];
    }
}

モーダル現在のコードで、提示されたVCでselfへの参照を設定します-例:

   MasterViewController* BViewController = [[BViewController alloc] init];
   BViewController.presentingController = self;
   [self presentModalViewController:BViewController animated:YES];

dismissBackToAこれで、AViewControllerサブクラスをオーバーライドするだけで済みます。

- (void) dismissBackToA
{
    [self dismissModalViewControllerAnimated:YES];

}

これにより、任意の数のモーダルviewControllerをデイジーチェーン接続できます...ジェネリックdismissBackToAはチェーンをAに「巻き戻し」ます。Aのオーバーライドメソッドは、モーダル(B)を閉じます。これにより、チェーン内の他のすべてのコントローラーが消去されますは標準のデリゲートとして機能しています-iOS5+presentControllerとの類似性を強調するために、指定しすぎています。presentingViewController私は非アークメモリに少し錆びていますが、それを保持せずに割り当てる必要があると思います。

iOS4.3シミュレーターが手元にないため、これを100%テストすることはできません...

アップデート

チェーンの最後までAへの参照を渡して、[self.referenceToA dismissModalViewControllerAnimated:YES]必要なときにいつでも送信することもできますが、この方法はもう少し一般的な感じがします。

また、これに注意する必要がありpresentModalViewController:animated:dismissModalViewControllerAnimated:6.0では非推奨になりました。これで、

- presentViewController:animated:completion: 
- dismissViewControllerAnimated:completion:

5.0で導入されました。

これらは引き続き機能しますが、警告として受け取ります。4.3のサポートを終了するか、将来的にOSバージョンを条件としてコードを作成する準備をする必要があります。

于 2013-03-26T02:51:32.463 に答える
0

これは、コントローラーを閉じるための良い方法ではありません。この目的のためだけにシングルトンを作成するのは悪い考えのようです。はるかに簡単な方法は、アンワインドセグエを使用してストーリーボードでそれを行うことですが、これはiOS 6でのみ機能すると思います(おそらくiOS 5でも)。コードでそれを実行したい場合は、委任またはNSNotificationsを使用して、AにCを却下させる必要があります(これによりBも却下されます)。また、コードでモーダルビューコントローラーを表示する場合は、この減価償却されたメソッドを使用するのではなく、代わりにpresentViewController:animated:completion:を使用してください。

編集後:

コントローラCから次のようにすることもできます。

[self.presentingViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];
于 2013-03-26T01:14:34.737 に答える