2

割り当てが解除されていないサブクラス化されたUIViewがあります。ビューのインスタンスを作成しているクラスは1つだけです。私の見解ではNSTimerivarがあります。そのタイマーをコメントアウトし、このビューコントローラにあるキャンセルボタンをタップすると、このビューのdeallocが呼び出されます。タイマーをコメントアウトしないと、deallocが呼び出されることはありません。

//CustomUIView
- (id) initWithFrame:(CGRect)frame 
{
    self = [super initWithFrame:frame];
    if (self) {
        _pollTimer = [[NSTimer scheduleTimerWithTimeInterval:0.2 target:self selector:@selector(onPollTimerFired:) userInfo:nil repeats:YES] retain];
    }
}

タイマーを一時停止したい場合があるので、このタイマーへの参照を保持したいと思います。これで、タイマーのビューにプロパティを設定でき、カスタムuiviewへの参照を持つクラスのdeallocメソッドで、そのビューを解放する前に無効にすることができます。このタイマーを外部のエンティティに公開したくないので、このアプローチはあまり好きではありません。

誰かアイデアはありますか?

4

3 に答える 3

7

NSTimer常にターゲットを保持します。これには2つの意味があります。

  1. ビュー(タイマーのターゲット)にタイマーを保持させないでください。これにより、サイクルが作成されます。

  2. タイマーがアクティブである限り、ビューの割り当てが解除されることはありません。

代わりに、invalidateビューが終了するたびにタイマーを呼び出す必要があります。deallocこれが行われると、参照カウントがゼロになったときにビューが評価されます。

通常、これはビューがスーパービューから削除されたときに発生します。それが発生するまでタイマーを使用し続けてから解放されるようにしたい場合は、オーバーライドremoveFromSuperviewしてタイマーを無効にしてからを呼び出すことができますsuper

于 2012-06-24T05:25:02.113 に答える
0

編集:

あなたの-dealloc方法で、これを試してください:

- (void) dealloc
{
    [_pollTimer invalidate];

    /*
        If not using ARC:
        [_pollTimer release], _pollTimer = nil;
        [super dealloc];
    */
}

superの実装を呼び出すのを忘れました-initWithFrame:!おっと!

- (id) initWithFrame:(CGRect)frame 
{
    if ((self = [super initWithFrame:frame]))
    {
        _pollTimer = [[NSTimer scheduleTimerWithTimeInterval:0.2 target:self selector:@selector(onPollTimerFired:) userInfo:nil repeats:YES] retain];
    }
    
    return self;
}

これははるかにうまくいくはずです。

于 2012-06-24T02:13:07.807 に答える
0

タイマーを保持しないでください。このようにタイマーをスケジュールします:_pollTimer = [NSTimer scheduleTimerWithTimeInterval:0.2 target:self selector:@selector(onPollTimerFired:) userInfo:nil repeats:YES];そしてあなたがそれを無効にしたいときはいつでも:[_pollTimer invalidate]

于 2012-06-24T04:54:31.507 に答える