【swift】Timer について

#Timer 
指定されたメッセージをターゲットオブジェクトに送信して、一定の時間間隔が経過した後に起動するタイマー。

##Declaration   宣言
```swift

class Timer : NSObject
```

##Overview 概要
タイマーは実行ループと連携して動作します。 実行ループはそれらのタイマーへの強力な参照を保持しているので、実行ループに追加した後にタイマーへのあなた自身の強力な参照を保持する必要はありません。
タイマーを効果的に使用するには、実行ループがどのように機能するのかを知っておく必要があります。 詳細については、Threading Programming Guideを参照してください。
タイマーはリアルタイムメカニズムではありません。 長時間の実行ループの呼び出し中、または実行ループがタイマーを監視していないモードにある間にタイマーの起動時間が発生した場合、次回の実行ループがタイマーをチェックするまでタイマーは起動しません。 したがって、タイマーが作動する実際の時間はかなり遅くなる可能性があります。 タイマー許容値も参照してください。
Timerは、Core FoundationのCFRunLoopTimerとフリーダイヤルブリッジされています。 詳細については、フリーダイヤルブリッジングを参照してください。


##繰り返しタイマーと非繰り返しタイマーの比較
作成時にタイマーを繰り返すかどうかを指定します。 繰り返しのないタイマーは一度起動してから自動的に無効になり、それによってタイマーが再度起動するのを防ぎます。 対照的に、繰り返しタイマーは起動してから、同じ実行ループで自分自身を再スケジュールします。 繰り返しタイマーは、実際の起動時間とは対照的に、常にスケジュールされた起動時間に基づいて自分自身をスケジュールします。 たとえば、タイマーが特定の時間に起動し、その後5秒ごとに起動するようにスケジュールされている場合、実際の起動時間が遅れても、スケジュールされた起動時間は常に元の5秒の時間間隔になります。 発射時間が１つ以上の予定発射時間を過ぎるまで遅れると、タイマーはその期間中に１回だけ発射される。 その後、タイマーは、起動後に、次に予定されている起動時間に再スケジュールされます。

##タイマー公差
iOS 7以降およびmacOS 10.9以降では、タイマーの許容値（tolerance）を指定できます。タイマーが作動したときのこの柔軟性により、節電と応答性の向上のために最適化するシステムの能力が向上します。タイマーは、その予定された発射日と予定された発射日と許容差との間のいつでも発火することができる。タイマーは、予定された開始日より前には開始されません。繰り返しタイマーの場合、ドリフトを避けるために、個々の発射時間に適用される許容範囲に関係なく、次の発射日が元の発射日から計算されます。デフォルト値はゼロです。これは、追加の許容誤差が適用されないことを意味します。システムは、toleranceプロパティの値に関係なく、特定のタイマーに少量の許容値を適用する権利を留保します。
タイマーのユーザーとして、タイマーの適切な許容範囲を決定できます。一般的な規則では、繰り返しタイマーの許容範囲を間隔の少なくとも10％に設定します。わずかな許容誤差でも、アプリケーションの電力使用量に大きなプラスの影響を与えます。システムは許容誤差の最大値を強制することができます

##実行ループでのタイマーのスケジューリング
タイマーは一度に1つの実行ループにのみ登録できますが、その実行ループ内の複数の実行ループモードに追加することはできます。タイマーを作成する方法は3つあります。
scheduleTimer（timeInterval：invocation：repeats :)またはscheduleTimer（timeInterval：target：selector：userInfo：repeats :)クラスメソッドを使用して、タイマーを作成し、既定のモードで現在の実行ループにスケジュールします。
init（timeInterval：invocation：repeats :)またはinit（timeInterval：target：selector：userInfo：repeats :)クラスメソッドを使用して、実行ループでスケジュールせずにタイマーオブジェクトを作成します。 （作成後、対応するRunLoopオブジェクトのadd（_：forMode :)メソッドを呼び出して、手動でタイマーを実行ループに追加する必要があります。）
タイマーを割り当て、init（fireAt：interval：target：selector：userInfo：repeats :)メソッドを使用してタイマーを初期化します。 （作成後、対応するRunLoopオブジェクトのadd（_：forMode :)メソッドを呼び出して、手動でタイマーを実行ループに追加する必要があります。）
実行ループでスケジュールされると、タイマーは無効になるまで指定された間隔で起動します。非繰り返しタイマーは、起動後すぐに無効になります。ただし、繰り返しタイマーの場合は、invalidate（）メソッドを呼び出してタイマーオブジェクトを自分で無効にする必要があります。このメソッドを呼び出すと、現在の実行ループからタイマーを削除するように要求されます。結果として、タイマーがインストールされたのと同じスレッドからinvalidate（）メソッドを常に呼び出す必要があります。タイマーを無効にするとすぐに無効になり、実行ループには影響しなくなります。次に、runループは、invalidate（）メソッドが返される直前、またはそれ以降の時点で、タイマー（およびタイマーに対する強力な参照）を削除します。いったん無効にすると、タイマーオブジェクトは再利用できません。
繰り返しタイマーが起動した後、指定された許容範囲内で、最後にスケジュールされた起動日以降のタイマー間隔の整数倍である最も近い将来の日付に次回の起動がスケジュールされます。セレクターまたは呼び出しを実行するための呼び出しにかかる時間が指定された間隔よりも長い場合、タイマーは次の起動のみをスケジュールします。つまり、タイマーは、指定されたセレクターまたは呼び出しを呼び出している間に発生していたはずの失敗した起動を補おうとしません。

##サブクラス化ノート
Timerをサブクラス化しないでください。

#Topics

##Creating a Timer

```swift

class func scheduledTimer(withTimeInterval: TimeInterval, repeats: Bool, block: (Timer) -> Void) -> Timer
```
**デフォルトモードでタイマーを作成し、現在の実行ループでスケジュールします。**

```swift

class func scheduledTimer(timeInterval ti: TimeInterval, target: Any, selector: Selector, userInfo: Any?, repeats: Bool) -> Timer
```
**デフォルトモードでタイマーを作成し、現在の実行ループでスケジュールします。**

ti秒が経過すると、タイマーが作動し、メッセージaSelectorをtargetに送信します。

```swift
class func scheduledTimer(timeInterval: TimeInterval, invocation: NSInvocation, repeats: Bool) -> Timer
```
**新しいタイマーを作成し、デフォルトのモードで現在の実行ループにスケジュールします**

ti秒が経過すると、タイマーが起動して呼び出しが呼び出されます。

```swift
init(timeInterval: TimeInterval, repeats: Bool, block: (Timer) -> Void)
```
**指定された時間間隔とブロックでタイマーオブジェクトを初期化します。**

```swift

init(timeInterval: TimeInterval, invocation: NSInvocation, repeats: Bool)
```
**指定されたオブジェクトとセレクタを使用してタイマーオブジェクトを初期化します。**

add（_：forMode :)を使用して、新しいタイマーを実行ループに追加する必要があります。その後、ti秒が経過した後、タイマーが作動し、メッセージaSelectorをtargetに送信します。 （タイマーが繰り返すように構成されている場合は、後で実行ループにタイマーを追加する必要はありません。）

```swift

init(fire: Date, interval: TimeInterval, repeats: Bool, block: (Timer) -> Void)
```

**指定されたブロックを使用して、指定された日時のタイマーを初期化します。**

```swift
init(fireAt: Date, interval: TimeInterval, target: Any, selector: Selector, userInfo: Any?, repeats: Bool)
```
**指定されたオブジェクトとセレクタを使ってタイマーを初期化します。**

add（_：forMode :)を使用して、新しいタイマーを実行ループに追加する必要があります。起動すると、タイマーはメッセージaSelectorをtargetに送信します。 （タイマーが繰り返すように構成されている場合は、後で実行ループにタイマーを追加する必要はありません。）

##Firing a Timer タイマーを起動する

```swift

func fire()
```
**タイマーのメッセージをターゲットに送信します。**

このメソッドを使用すると、通常の起動スケジュールを中断することなく繰り返しタイマーを起動できます。 タイマーが繰り返されていない場合は、予定された開始日が到来していなくても、開始後に自動的に無効になります。

##Stopping a Timer タイマーを停止する

```swift

func invalidate()
```
**タイマーが二度と起動しないように停止し、実行ループからの削除を要求します。**

このメソッドは、RunLoopオブジェクトからタイマーを削除する唯一の方法です。 RunLoopオブジェクトは、invalidate（）メソッドが返される直前またはそれ以降の時点で、タイマーへの強い参照を削除します。
ターゲットおよびユーザー情報オブジェクトで構成されている場合、受信側はそれらのオブジェクトへの強い参照も削除します。
特別な考慮事項
このメッセージは、タイマーがインストールされているスレッドから送信する必要があります。 このメッセージを別のスレッドから送信すると、タイマーに関連付けられている入力ソースがその実行ループから削除されず、スレッドが正常に終了しなくなる可能性があります。

##Retrieving Timer Information タイマー情報の取得

```swift
var isValid: Bool
```
**タイマーが現在有効かどうかを示すブール値。**

レシーバがまだ起動可能な場合はtrue、タイマーが無効化されていて起動できなくなった場合はfalse

```swift
var fireDate: Date
```
**タイマーが作動する日付。**

タイマーが無効になった場合は、タイマーが終了した最後の日付。
このプロパティを設定して、繰り返しタイマーの起動時間を調整できます。タイマーの次の起動時間をリセットすることは比較的高価な操作ですが、状況によってはより効率的な場合があります。たとえば、将来、アクションを不定期に複数回繰り返す場合に使用できます。単一のタイマーの起動時間を調整すると、複数のタイマーオブジェクトを作成し、それぞれを実行ループでスケジュールしてから破棄するよりも費用が少なくて済みます。
無効になっているタイマーの開始日は変更しないでください。これには、既に発行済みの繰り返しのないタイマーも含まれます。まだ発生していない繰り返しのないタイマーの開始日を潜在的に変更することができますが、潜在的な競合状態を回避するために、常にタイマーが接続されているスレッドから変更する必要があります。
isValidメソッドを使用して、タイマーが有効であることを確認します。

```swift
var timeInterval: TimeInterval
```
**タイマーの時間間隔（秒単位）。**

タイマーが繰り返しでない場合は、時間間隔が設定されていても0を返します。

```swift
var userInfo: Any?
```
**受信側のuserInfoオブジェクト**

タイマーが無効になった後は、このプロパティにアクセスしないでください。 タイマーが有効かどうかをテストするには、isValidを使用します。

##Configuring Firing Tolerance 発射耐性の設定

```swift

var tolerance: TimeInterval
```
**タイマーが起動する予定の起動日からの経過時間。**
デフォルト値はゼロです。これは、追加の許容誤差が適用されないことを意味します。
タイマーの許容範囲を設定すると、スケジュールされた開始日より遅く開始することができます。タイマーが作動したときにシステムに柔軟性を持たせることで、節電と応答性を向上させるためにシステムが最適化する能力が高まります。
タイマーは、その予定された発射日と予定された発射日と許容差との間のいつでも発火することができる。タイマーは予定された発射日の前に発火しません。繰り返しタイマーの場合、ドリフトを避けるために、個々の発射時間に適用される許容範囲に関係なく、次の発射日が元の発射日から計算されます。このプロパティの値にかかわらず、システムは特定のタイマーにわずかな許容範囲を適用する権利を留保します。