5

サーバーに接続している iOS アプリがあります。切断された場合は、トップ ビュー コントローラーを閉じて、「サーバーに接続中」のビュー コントローラーに戻れるようにしたいと考えています。問題は、View Controller 間の遷移中を含め、いつでも切断が発生する可能性があることです。

ビュー コントローラの階層は次のようになります。

  1. ConnectingToServerViewController
  2. SignInViewController
  3. MainAppViewController
  4. その他のビュー コントローラー

切断が検出されたら、ビュー階層を次のように折りたたむ必要があります。

  1. ConnectingToServerViewController

したがって、切断が検出されると、このメソッドが呼び出されて、ConnectingToServerViewController提示されたものをすべて破棄し、サーバーへの接続試行に戻ります。

- (void)restartSession
{
    if (self.presentedViewController) {
        [self dismissViewControllerAnimated:NO completion:nil];
    }
}

ただし、ビューの遷移が発生しているときに閉じようとすると、次のようなエラーが発生します

*** Assertion failure in -[UIWindowController transition:fromViewController:toViewController:target:didEndSelector:], /SourceCache/UIKit/UIKit-2380.17/UIWindowController.m:211

attempt to dismiss modal view controller whose view does not currently appear. self = <YYYYYViewController: 0x2089c8a0> modalViewController = <XXXXXViewController: 0x208e6610>
attempt to dismiss modal view controller whose view does not currently appear. self = <WWWWWWViewController: 0x1fd9e990> modalViewController = <YYYYYViewController: 0x2089c8a0>

1 つ目はアプリをクラッシュさせ、2 つ目は何も破棄せず、現在表示されているビュー コントローラーを表示し続けます。

考え:

  1. いつ遅延を開始するかわからないため、遅延は機能しません
  2. ビューの遷移がいつ完了したかを追跡する方法はありますか?
  3. すべてのView ControllerはwillAppear、didAppearをオーバーライドし、安全に閉じられるときにアプリに警告する必要がありますか?
  4. おそらく、却下する代わりに、新しいルート ビュー コントローラーを設定する必要がありますか?
  5. オーバーライドされたすべての view(will|did)(dis)?appear メソッドが適切なスーパー メソッドを呼び出すことを確認しました。
  6. すべてのビュー コントローラーがビュー (did|will)appear メソッドをオーバーライドして状態を追跡する必要があるソリューションは、新しいビュー コントローラーの基本クラスを設定するのを忘れた場合に問題が発生する可能性があるように思えます。
4

4 に答える 4

0

私にとってうまくいった方法の 1 つは、新しいビュー コントローラーをルート ビュー コントローラーに割り当てることです。そうすれば、古い階層のビューは、新しいコントローラーを使用している間、アニメーション化してハート コンテンツに移行できます。

例えば

- (void)restartSession
{
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
    ConnectingToServerViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"ConnectingToServerViewController"];
    vc.modalPresentationStyle = UIModalPresentationFullScreen;
    [UIApplication sharedApplication].delegate.window.rootViewController = vc;
}

ただし、これのすべての欠点を認識しているかどうかはわかりません。おそらく、ぶら下がっている強い参照のために、古いView Controllerが解放されることはありませんか? ConnectingToServerViewController を再利用しなくなったため、毎回再作成する必要があります。

iOS で複数のビュー コントローラーを管理および破棄するためのこの回答で見たものに基づいてコードを作成しました。

于 2013-07-23T07:20:06.537 に答える