1

アプリデリゲートを使用して、ViewController間を移行しています。サーバーからのメッセージに基づいて、デリゲートがView Controllerが不要になったと判断した場合、現在のビューを削除して別のビューに置き換える必要があります。現在、私のコードは次のようになっています。

- (void) showFight: (NSNotification*) notification
    {
        if(self.window.rootViewController != self.fightViewController)
        {
            NSDictionary* dict = [notification userInfo];

                FightViewController *fightView = [[FightViewController alloc]
                                                  initWithNibName:@"FightViewController" bundle:nil];
                fightView.userId = _userId;

                self.fightViewController = fightView;
                [fightView release];
                [self.radarViewController.view removeFromSuperview];  // Doesn't work.

                self.window.rootViewController = self.fightViewController;
                [self.fightViewController showMonster:dict];

        }
    }

ビューコントローラーからサウンドエフェクトがバックグラウンドで聞こえるので、ビューコントローラーが削除されていないことはわかっています。

いつでも1つのViewControllerのみをメモリに入れたいので、ViewControllerを完全に破棄したいと思います。上記のコードに示すように、毎回最初からViewControllerを作成する予定です。私はこれを不適切に行っていますか?

4

2 に答える 2

2

ここでの問題は、View Controller を解放していないようです。コードで実際に何が起こっているかを考えてみましょう:

[self.radarViewController.view removeFromSuperview];

スーパー ビューからビューを削除します。ビューコントローラーはまだ存在しており、ビューに表示するものを制御し、あなたの場合は明らかにサウンドを再生しています。

簡単に言えば、View Controller はオブジェクトです。それは子、ビューを持っています。それは別のオブジェクトです。別のビューからビューを削除しますが、削除されたビューを制御するオブジェクトはまだ生きています (実際には、ビュー オブジェクトも生きています)。

ビュー コントローラー全体を強制終了する場合は、スーパービューからビューを削除した後にこれを呼び出します。

[self.radarViewController release];

または、ビューが保持プロパティである場合(コードを見て推測します)、次も使用できます。

self.radarViewContoller = nil;

合成されたセッターで自動的に解放されます。

ビュー コントローラーが解放されると、その参照カウントが 1 減算されます。参照カウントがゼロになると、コントローラーの割り当てが解除されます。

于 2011-04-28T13:59:54.333 に答える
0

これまでのところ、サーバー通知に新しい ViewController を追加し、現在のビューを new Viewに変更することが問題であることを理解しています。参照はビューの更新に役立たないため、まず、以下のようにビュー コントローラーを追加する必要があります。

[self.window.rootViewController.view addSubview: self.fightViewController.view]

私の意見では、コントローラーにタグを付け、コントローラーを追加する前に、コントローラーが既にメモリに存在する場合はオブジェクトのプールがリークすることを確認する必要があります。メモリリークにはノーと言ってください!!

- (void) showFight: (NSNotification*) notification
{
      UIView *fightView = (UIView *)[self.window.rootViewController.view viewWithTag: FIGHT_VIEW_TAG];
      if (self.window.rootViewController.view.tag  != fightView.tag) {

          NSDictionary* dict = [notification userInfo];
          FightViewController *fightView = [[FightViewController alloc]
                                               initWithNibName:@"FightViewController" bundle:[NSBundle mainBundle]]; 

          //Remove the current view.
          [self.window.rootViewController.view removeFromSuperview];   // If you're adding the fighting View in the root View, then why are you trying to remove current view through radar controller which has already added in the window (root view). 

          fightView.userId = _userId;
          [fightView setTag: FIGHT_VIEW_TAG];
          [self.window.rootViewController.view addSubView: self.fightViewController.view]; 

          [self.fightViewController showMonster:dict];
          [fightView release];
  }
}

要件が異なるまで、それらをグローバルにする必要はありません。

于 2011-04-28T14:06:10.030 に答える