2012-02-24 25 views
1

NSTimerを使用しているときに問題が発生しました。 のは、私はこのアーキテクチャを持っていると仮定しましょう:NSTimerでクラッシュする可能性があります

ThreadedClass.mは(NSTimer *タイマーが含まれています。)

- (id) init { 
    if (self = [super init]) { 
    // do blablabla 
    [self launchAThread]; 
    } 
    return self; 
} 


- (void) launchAThread { 
    [NSThread detachNewThreadSelector:@selector(selectorToMyThreadFunction) 
          toTarget:self 
          withObject:nil]; 
} 


- (void) selectorToMyThreadFunction { 
    //I do my stuff in here 
    //Then i relaunch a Timer to call this function 
    //periodically but it has to be "atomic" so no 
    //repeating timer since i don't know the time 
    //this function will take 

    //I do some [self changeSomething]; 

    [self restartTimer]; 

    //MyThread ends here (and might be recreated by the Timer's bip 
} 

- (void)restartTimer { 
    if (![NSThread isMainThread]) { 
     [self performSelectorOnMainThread:@selector(restartTimer) 
          withObject:nil 
          waitUntilDone:NO]; 
     return; 
    } 

    [timer invalidate]; 
    [timer release]; 
    timer = [[NSTimer scheduledTimerWithTimeInterval:interval 
               target:self 
              selector:@selector(launchWithTimer:) 
              userInfo:nil 
              repeats:NO] retain]; 
} 

- (void) launchWithTimer:(NSTimer *)theTimer { 
    if (theTimer == timer) 
    { 
    [timer release]; 
    timer = nil; 
    [self launchAThread]; 
    } 
    else 
    { 
    //Nothing to be done in here, a user launch a thread manually 
    } 
} 

それでは、クラスのalloc、それのユーザーを想定し、直後にそれを解放してみましょう。私のタイマーはまだ生きていて、オブジェクトも(タイマーによって作られた保持があるので)。 タイマが起動すると、[self launchAThread]が実行され、タイマが無効化されて解放され、retainCount = 0のオブジェクトが解放されます。もう一度、オブジェクトが直ちに解放されるとします。これはクラッシュを引き起こし、私の心に正しいことを止めるために何もできません。

私は同意します、これは多くの前提ですが、誰かがすでにこの問題を抱えていて、それをどのように解決したかを知りたいのです。

読んでいただきありがとうございます。私は明確だったと思います! :)

答えて

0

でそれを解放/保持していないことを意味している、あなたのためのタイマーを保持しますどんなときも。

私の問題を解決するために、私はこのクラスのユーザーであるためにスレッドとタイマーの部分を行う新しいクラスを追加しました。

1

あなたはそれを解放する前に必ずタイマーを無効にする必要があります。タイマーがビューコントローラの一部である場合、私は常にviewWillDisappearで無効にしています。私にとっては、NSTimersが所有者を保持するのはとても奇妙です。私は最善の方法は - (void)cleanUpメソッドを作成することだと思います。これはタイマーを無効にし、クラスのユーザーに解放前に常にクリーンアップを使用するよう警告します。誰かがより良い方法を知っているなら、私は喜んでくれるでしょう。

+0

はい私は今やっている。しかし、あなたのように、もしあれば別の方法を知りたいです:)。とにかくありがとう – delannoyk

+0

私はライブラリを作っているので、いつでもユーザーがcleanUp関数を呼び出すことはできません。だから私の問題を解決するために、私は新しいクラスを追加しました:このクラスのユーザーであるようにスレッドとタイマーの部分を行う新しいクラスと私はクリーンアップする必要があることを知っている! – delannoyk

0

繰り返しタイマーを使用していない限り、dispatch_afterを使用しないでください。あなたはNSTimerオブジェクトの頭痛と頭上を救うでしょう。また、GCDに固執すれば、detachNewThreadSelector:への呼び出しも避けることができます。

0

NSRunloopあなたは、私がライブラリを作ってるんだので、私は、ユーザーがクリーンアップ関数を呼び出すと仮定することはできませんすべての

+0

本当に私の質問ではありませんでした。とにかくありがとう – delannoyk

0

私は最初にcleanUpの種類の関数も使用しました。 私はまた、オブジェクトBを保持しているオブジェクトBを所有するオブジェクトを所有しています。オブジェクトAが割り当て解除されると、オブジェクトBは解放されますが、タイマーはそれを保持しているためBが存続します。その後、タイマーを起動したメソッドでは、デリゲート関係を使用してオブジェクトA→ハードクラッシュにコールバックしています。これは、オブジェクトAがBのタイマーを "クリーンアップ"する必要がある場所です。これは、他のオブジェクトもオブジェクトBに依存しているにもかかわらず、他の問題につながる可能性があります。また、クラスAはクラスBの実装の秘密を知ってはいけません。あなたがそれをリリースしてもBが死ぬかどうか分からないので、誰かがそれを保持していたかもしれないことを知らないので、解放の前に解放されます(〜D *** NSTIMER)... :-P

関連する問題