2012-11-23 10 views

答えて

27

はい、NSTimerは、(特にリピートタイマーで)強い基準サイクル(特にリピートサイクル)を引き起こす可能性があるtargetへの強い参照を維持します。あなたの例では、タイマーは繰り返されず、遅延が0.5にすぎないため、最悪の場合のシナリオでは、0.5秒で自動的に解決される強力な参照サイクルになります。

しかし未解決の強い基準サイクルの一般的な例は、繰り返しNSTimerプロパティとUIViewControllerを持っているであろうが、NSTimerUIViewControllerへの強い参照を持っているので、コントローラは保持されてしまうであろう。

したがって、NSTimerをインスタンス変数として保持している場合、強い参照サイクルを解決するには、invalidateとする必要があります。 scheduledTimerWithTimeIntervalを呼び出すだけでインスタンス変数に保存していない場合(例のように)、NSTimerが完了すると強力な参照サイクルが解決されます。

そして、あなたはNSTimersを繰り返すことを扱っている場合は、強力な基準サイクルが解決されるまでdeallocは明らかに呼び出されませんので仕方によって、NSTimerの所有者のdeallocinvalidateにそれらをしようとしないでください。例えば、UIViewControllerの場合、viewDidDisappearで行うことができます。

ちなみに、Advanced Memory Management Programming Guideは、強い参照サイクルが何であるかを説明しています。明らかに、弱い参照の適切な使用を説明しているセクションにありますが(これはNSTimerがターゲットへの強い参照を使用しているという事実を制御できないためです)、ここでは該当しませんが、強力なリファレンスサイクルがうまくいきます。


あなたのNSTimerはMacOSの10.12とiOS 10で、selfへの強い参照を保持するために、以降、あなたはブロック表現を使用して、weakSelfパターンを使用することができますしたくない場合は、次の

typeof(self) __weak weakSelf = self; 
[NSTimer scheduledTimerWithTimeInterval:0.5 repeats:false block:^(NSTimer * _Nonnull timer) { 
    [weakSelf showButtons]; 
}]; 

ところで、私はあなたがshowButtonsと呼んでいることに気付きました。あなたは自分のビューにいくつかのコントロールを表示しようとしている場合、あなたは完全にNSTimerの使用を排除し、のような何かができる:これはNSTimerオブジェクトの保持の問題を受けて、両方を実行しない

self.button1.alpha = 0.0; 
self.button2.alpha = 0.0; 

[UIView animateWithDuration:0.25 
         delay:0.5 
        options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionAllowUserInteraction 
       animations:^{ 
        self.button1.alpha = 1.0; 
        self.button2.alpha = 1.0; 
       } 
       completion:nil]; 

1つのステートメント内でのボタンの遅延と表示が優雅に表示されます。showButtonsメソッドで追加の処理を行っている場合は、completionブロックに追加することができます。

+0

偉大な答えですが、実際にはNSTimer *タイマーの.hファイルで実際にdeclereしていないということを明確にしていないかもしれません。.mファイルにそのコードを追加するだけで、無効にしたり、 。この場合、タイマーを使用してもOKですか、または私が提供したコードを使用する方が良いですか? – Alessandro

+0

@Alessandro私は実際にあなたがタイマーのために象牙を維持していないと推測しました。しかし、明らかに、 'viewWillDisappear'で' invalidate'をしたいのであれば、そうする必要があります。 (さて、あなたは.hにプライベートイーバールを置く必要はありません;プライベートクラスの拡張はより良いです)。そして、あなたは 'NSTimer'を' nil'に設定することに関して言及しました。これは強い基準サイクルを解決しないことに注意してください。タイマーは完了する必要があります(繰り返されません)か、またはあなたは新しいイールを使って '無効にする'必要があります。 – Rob

1

を使用しています

、[はい、あなたはそれがセレクタを発射した後、ゼロに設定する必要があります。

あなたのクラスが何らかの理由で割り当て解除される場合に備えて、それを保存することも安全です。必要な場合は[timer invalidate]にすることができます。

+0

に、あなたがする' nil'それ自身はありませんが。 (反復していないと仮定して)発火後に自動的に解放されます。 – Rob

1

はい、あなたは使用することができます。myTimer=[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(showButtons) userInfo:nil repeats:NO]; そして、あなたはそのプロパティ `weak`を作る場合、あなたのviewDidDisappear [myTimer invalidate]