9
@interface someview:UIView{
  NSTimer* timer;
}
@end

@implementation someview

-(void)dealloc{
  NSLog(@"dealloc someview");
  [timer invalidate];
  timer = nil;
}
-(void)runTimer{
//
}
-(void)someMethod{

  timer = [NSTimer timerWithTimeInterval:2.0f target:self selector:@selector(runTimer) userInfo:nil repeats:YES];
}

@end

一部のビューを解放しても、dealloc は呼び出されず、タイマーは実行され続けます。

「timer = [NSTimer schedule....」の部分をコメントアウトすると、dealloc が呼び出されます。つまり、コードの他の部分はすべて正常に機能しており、タイマーが原因です。runTimer メソッドは空です。つまり、タイマーが私をいじっているだけです。

4

3 に答える 3

23

UIView 内で NSTimer を使用する場合の最善の解決策は、removeFromSuperview メソッドをオーバーライドすることだと思います。

- (void)removeFromSuperview
{
    [timer invalidate];
    timer = nil;

    [super removeFromSuperview];
}

ここで留意すべき唯一のことは、removeFromSuperview が他の UIView の super dealloc メソッドからも自動的に呼び出される可能性があるため、timer が nil オブジェクトでないことを確認する必要があるということです。チェックする条件をラップできます。

于 2011-05-19T18:54:23.980 に答える
14

NSTimer はターゲットを保持します。したがって、ビューの割り当てを解除する前に、タイマーを無効にする必要があります。

于 2011-04-14T22:30:53.057 に答える
1

前述のように、タイマーはターゲットを保持します。タイマーが無効になるまで、タイマーとビューの間に保持サイクルがあるため、ビューは割り当て解除されません。

サブクラス化によってビュー階層から削除されたときにタイマーを無効にしますdidMoveToSuperview。これは、ビュー関連の変更(スーパービューの変更など)があるときにシステムによって呼び出されます。「removeFromSuperview」はremoveFromSuperview、UIView で呼び出されたときにのみ呼び出されます

- (void)didMoveToSuperview
{
    [super didMoveToSuperview];

    if (!self.superview)
    {
        [timer invalidate];
        timer = nil;
    }
}
于 2013-12-18T15:28:45.240 に答える