2

私が取り組んでいるプロジェクト (このコードを取得し、デバッグしようとしています) では、オブザーバーによって呼び出される関数があります。オブザーバーは、画面に表示されるデータを更新するメソッドを呼び出します。この更新が行われている間 (更新が行われるまでに数秒かかります)、ユーザーはナビゲーション バーの [戻る] ボタンを押すと、dealloc 呼び出しが発生します。メソッドの実行中に、dealloc 呼び出しによってすべての ivar が解放され、メソッドが ivar にアクセスしようとすると、最終的に EXC_BAD_ACCESS が発生します。update メソッドの構造体も@synchronizedブロックで囲みます。

- (void)update {

@synchronized(self){
  // some code here...
  // Also access ivars here.
  }

}

割り当てを解除する前に、まずメソッドを終了するようにコントローラに指示するにはどうすればよいですか? dealloc で条件付きの while ループを実行しようとしましたが、効率的ではないようです。また、コントローラーが解放された場合も完全には実行されず、デッドロックのままになります。解決策は簡単な気がしますが、長い一日の仕事で頭がおかしくなり、それについて考えることができません。

4

4 に答える 4

2

retain実行時間の長いメソッドの実行中に参照カウントがゼロにselfならないように呼び出すことができます。その方法で解放を回避します。

- (void) update {
    [self retain]

    // do work ...

    [self release]
 }
于 2012-06-20T20:42:09.070 に答える
1

必要な作業をブロックに入れると、コンパイラはブロック内で参照されているすべてのオブジェクト (self を含む) を自動的に保持します。例えば:

- (void)update {
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        // some code here, access ivars, do whatever you want
    }];
}

update メソッドはすぐに戻り、ブロックはメインの実行ループで実行されるようにスケジュールされます (ここではセカンダリ スレッドは関与しません)。

更新作業が長時間実行されるタスクである場合は、メインのキューの代わりにバックグラウンド キューを使用し、(そのブロック内で) 別のブロックをメイン キューで実行するようにスケジュールし、作業が完了したら UI と対話することができます。

于 2012-06-20T20:51:53.297 に答える
0

あなたは NavigationBar について話しているので、NavigationController が UIViewController クラスへの参照を解放し、それが ivar を保持していることが私の推測です。それを回避する1つの方法は、他の回答が示唆するように、計算が行われるまでオブジェクトをviewcontroller内に保持することです。ただし、実行中の計算が、そのビューに表示されるデータを計算するために行われる場合、次に同じビューを開いたときに、ビューを最初から再読み込みします。

私がすることは、ユーザーが戻るボタンを押したときに解放されないように、navigationcontroller の外で作業している ViewController への参照を保持することです。

その後、ユーザーが同じビューに戻ってきた場合、データは既に読み込まれています。同じ参照を使用してもう一度プッシュするだけです。

例:

@interface YourRootViewController : UIViewController {
    YourNextControllerClass *nextController;
}

@property (nonatomic, retain) YourNextControllerClass *nextController;

@end

一番上のViewControllerのViewDidLoadで:

self.nextController = [[[YourNextControllerClass alloc] initWithNibName:@"YourNextControllerNib" bundle:nil] autorelease];

ビューを表示する場合:

[myNavigationController pushViewController:nextController animated:YES];

ユーザーが戻るボタンを押した場合、viewcontroller は解放されないため、もう一度押すと、すべてが元のままになります。

于 2012-06-20T21:17:28.610 に答える
0

解決策は、そのオブジェクトをメソッドの最後まで存続させたいかどうかによって異なります。ただし、@synchronized (self) も使用します。self の割り当てが解除され、@synchronized が self のロックを解除しようとするとどうなるか非常に心配なので、この場合はロックを維持するようにします。(ただし、@synchronized を実行してから大量のコードを実行することは、私の意見では良い考えではありません。@synchronized は、デッドロックを回避するために可能な限り最小限のコードに使用する必要があります)。

ARC を使用すると、メソッド内でオブジェクトを維持するのは簡単です。

typeof (self) myself = self; 

自己への強力な参照を作成します。また、self の代わりにメソッド本体で自分自身を使用することをお勧めします。

オブジェクト「自己」を存続させたくない場合は、通常のケースです。

__weak typeof (self) weakSelf = self; 

次に、自己がまだそこにあることを確認したい場所に書き込みます

typeof (self) strongSelf = weakSelf;
if (strongSelf != nil) {
}
于 2016-10-21T08:35:46.217 に答える