クロックの使用しているクラス

2010. 05. 23
前回作った『基礎からのiPhone SDK 改訂版』の『クロックの作成』に関して、内容を掘り下げたいと思います。

NSObject
    |
    ∟NSDate
    |
    ∟NSFormatter
    |        ∟NSDateFormatter
    |
    ∟NSTimer


●NSTimerクラス

NSTimerクラスは、単純なタイマーやタイマーオブジェクトの生成に使用します。

タイマーは一定時間間隔で待機し、発火すると指定したメッセージをターゲットオブジェクトへ送信します。

例えば、ウィンドウにメッセージを送信するNSTimerオブジェクトを生成し、一定時間間隔で更新を伝えることができます。

タイマーは実行ループと連携して動きます。

タイマーを効果的に利用するには、実行ループの動作を理解している必要があります。
(『NSRunLoop』と『Threading Programming Guide』を参照)

特に、実行ループがタイマーを保持している場合、実行ループに追加したタイマーを後で解放するよう注意してください。

タイマーはリアルタイムの構造ではなく、実行ループモードの時のみ追加したタイマーが実行され、タイマーの発火時間が経過したかチェックをして、過ぎていれば発火します。

通常、実行ループの管理する様々な入力ソースの原因により、タイマーの有効な時間間隔の限界は50~100msecです。

もしタイマーの発火時間間隔より実行ループモードのタイマーの監視期間が長い場合は、実行ループがタイマーをチェックする次の時間まで発火しません。

従って、実際に発火可能な時間間隔で、タイマーの発火時間をスケジュールすることが重要です。

NSTimerオブジェクトには、『toll-free bridged』の対象としてCore FoundationのCFRunLoopTimerRef型があります。

これはFoudationオブジェクトを橋渡ししてCore Foundationの型に変換し、関数やメソッドで呼び出せることを意味します。

例えば、NSTimer *パラメータをメソッドで参照する際、CFRunLoopTimerRefに渡し、CFRunLoopTimerRefパラメータとして関数で参照でき、(コンパイラの警告を抑えるために型変換をして)NSTimerインスタンスに渡すこともできます。

型変換に関する詳細は『Introduction to Carbon-Cocoa Integration Guide』を、Core Foundationについては『CFRunLoopTimer Reference』を参照してください。

リピート対非リピートタイマー

タイマー生成時に、リピートか非リピートかを指定します。

非リピートタイマーの場合、発火は1回のみで自動的に無効になり、以降のタイマーからの発火を防ぎます。

リピートタイマーは対照的に、同じ実行ループ上で自身を再スケジュールして発火します。

リピートタイマーは実際の発火時間と異なり、常に発火時間を自身でスケジュールします。

例えば、タイマー自身が常に5秒間隔で発火するスケジュールを立てても、実際には本来の5秒間隔よりも遅延した間隔で発火します。

発火時間が遅延し、発火時間のスケジュールが1回以上過ぎても、再スケジュールされた次の発火時間でのタイマーの発火は1回のみです。

実行ループでのタイマーのスケジューリング

実行ループ内に複数の実行ループモードが追加されていても、1回の実行ループで登録できるタイマーオブジェクトは1つだけです。

タイマーを生成するには以下の3通りがあります。

・scheduledTimerWithTimeInterval:invocation:repeats:またはscheduledTimerWithTimeInterval:target:selector:userInfo:repeats:クラスメソッドを使用し、デフォルトモードで現在の実行ループにタイマーとスケジュールを生成する。

・timerWithTimeInterval:invocation:repeats:またはtimerWithTimeInterval:target:selector:userInfo:repeats:クラスメソッドを使用して、タイマーオブジェクトの生成と実行ループ外でスケジューリングをする。
(後で、NSRunLoopオブジェクトに対応するaddTimer:forMode:メソッドでタイマーを追加生成し、実行ループで手動で呼び出す必要があります)

・initWithFireDate:interval:target:selector:userInfo:repeats:メソッドを使用して、タイマーの生成と初期化をする。
(生成後、NSRunLoopオブジェクトに対応するaddTimer:forMode:メソッドでタイマーを追加生成し、実行ループで手動で呼び出す必要があります)

実行ループでスケジュールされるのは一度だけで、指定した間隔でタイマーが発火すると次回まで無効になります。

非リピートタイマーは、発火後すぐに自身でタイマーオブジェクトを無効にします。

しかしリピートタイマーは、invalidateメソッドを呼び出してタイマーオブジェクトを無効にする必要があります。

現在の実行ループからタイマーを除去するにはこのメソッドを呼び出せばいいのですが、タイマーを組み込んだ同じスレッドからinvalidateメソッドを常に呼び出す必要があります。

タイマーの無効化は直後のみ使用不可にするためのもので、実行ループで長く作用しません。

invalidateメソッドが戻る直前か少し後の時点で、実行ループはタイマーを除去・解放します。

一度無効にしたタイマーオブジェクトは再利用することはできません。


●NSDateクラス

NSDateオブジェクトは時間の1点を表します。

NSDateはクラスクラスタで、1つのパブリックスーパークラスであり、時間に関する値とプログラムインターフェイスの指定を宣言します。
(クラスクラスタやパブリックスーパークラスに関しては『Cocoa Fundamentals Guide/Cocoaオブジェクト/クラスクラスタ』を参照してください)

NSDateを使って生成したオブジェクトはdateオブジェクトと呼ばれます。

これは不変オブジェクトです。

クラスクラスタという性質のため、NSDateクラスが返すオブジェクトは抽象クラスのインスタンスではなく、プライベートサブクラスのインスタンスになります。

たとえdateオブジェクトのクラスがプライベートであってもインターフェイスはパブリックであり、抽象スーパークラスであるNSDateによって宣言されています。

一般的に、dateオブジェクトをインスタンス化する際には、最適なdate~クラスメソッドが呼び出されます。

NSDateは抽象クラスで、日時の生成、比較、表示や、期間の計算などの機能を提供します。

NSDateはプログラムインターフェイスを通して現在の最適なdateオブジェクトを要求して返します。

NSDateは、不変の時点から現在までの時間を表す、軽量なdateオブジェクトを返します。

このクラスは、任意の暦を表す基礎を提供するように設計されています。

NSDateの唯一の原始的なメソッドはtimeIntervalSinceReferenceDateで、他の全てのNSDateインターフェイスメソッドの基礎を提供します。

このメソッドは2001年1月1日(GMT)を基準とした参照時間を返します。

生成した日付を表す文字列を含み、dateFromString:メソッドやstringFromDate:メソッドを使って、NSdateFormatterのインスタンスの解析に使用してください。
(詳細は『Date Formatting Programming Guide for Cocoa』の『Date Formatters』を参照してください)

NSDateのモデルは1582年10月でユリウス暦からグレゴリオ暦に変更されていて、暦の計算を連携して行うNSCalenderへの変換時に適用されます。

注:ただし、いくつかのロケールではグレゴリオ暦の採用時期が異なっており、例えばイギリスでは1752年9月まで切り替えられていませんでした。

NSDateには、『toll-free bridged』の対象としてCocoa FoundationのCFDate型があります。

これはFoudationオブジェクトを橋渡ししてCore Foundationの型に変換し、関数やメソッドで呼び出せることを意味します。

例えば、NSDate *パラメータをメソッドで参照する際、CFDateRefに渡し、CFDateRefパラメータとして関数で参照でき、(コンパイラの警告を抑えるために型変換をして)NSDateインスタンスに渡すこともできます。

サブクラス化の注意

NSDateのサブクラス化の主な理由は、特定の暦のシステムを操作するのに便利なメソッドのクラスを生成することです。

しかし、例えば日付と時刻の細かい時間の断片を取得するなど、他の理由でNSDateクラスのカスタム化する場合もあります。

メソッドのオーバーライド

プライベートまたはパブリックな、動作の異なるNSDateのサブクラスを作る場合、以下の事を行う必要があります。

・(絶対参照日に関連付けした)日付と時刻の値を保持に適したインスタンス変数の宣言

・正しい日付と時刻の値に基づいたインスタンス変数を提供する、timeIntervalSinceReferenceDateインスタンスメソッドのオーバーライド

・initWithTimeIntervalSinceReferenceDate:をオーバーライドした、指定された初期化メソッド

暦のシステムを表すサブクラスを生成する場合、この暦の単位に分割した過去と未来の期間のメソッドを定義する必要があります。

何故なら、NSDateクラスはNSCopyingとNSCodingのプロトコルを採用しており、サブクラスはこれらのプロトコルを全てのメソッドで実装する必要があるためです。

特別な考慮事項

サブクラスはNSDateの使う絶対参照日(2001年1月1日 GMT)と異なる参照日を使う事ができます。

その場合はメソッドを実装する際に、timeIntervalSinceReferenceDateとinitWithTimeIntervalSinceReferenceDate:を使って絶対参照日を設定します。

この参照日は、メソッドのタイトルの中で参照できる絶対参照日です。

これらのメソッド内で絶対参照日を使用しない場合、生成したサブクラスのNSDateオブジェクトとプライベートサブクラスのNSDateオブジェクトの比較は動作しません。


●NSDateFormatterクラス

NSDateFormatterのインスタンスはNSDate(とNSCalendarDate)オブジェクトの表す文字列を生成し、NSDateオブジェクトの中の日付と時刻を変換して表します。

日付と時刻を、プリセットフォーマットスタイルまたはカスタムフォーマット文字列で柔軟に表現する事ができます。

一般的には、フォーマットスタイル(timeStyledateStyleNSDateFormatterStyleを参照)の使用より、ユーザの好みを反映したスタイルを提供するカスタムフォーマットの文字列の使用を推奨します。

フォーマットスタイルはロケール設定を反映します。

フォーマッタの動作とOSのバージョン

Mac OS X v10.4以降は、NSDateFormatterに2つの動作モード(または動作)があります。

新旧の全動作の説明は、DateFormatter Programming Guide for Cocoaを参照してください。

iPhone OSでの注意:iPhone OSがサポートしているのは、10.4+の動作のみです。
10.0-スタイルのメソッドとフォーマットの文字列はiPhone OSで利用できません。

デフォルトでは、Mac OS X v10.4でもNSDateFormatterのインスタンスは、Mac OS X v10.0から10.3と同じ動作をします。

Mac OS X v10.5以降は、NSDateFormatterのデフォルトは10.4+の動作になります。

(後方互換性のために)古いスタイルのdate formatterを生成する場合は、フォーマッタの初期化にinitWithDateFormat:allowNaturalLanguage:を使います。

新しい動作を使用する場合は、formatterの初期化にinitを使います。

必要な場合、デフォルトのクラスの動作をsetDefaultFormatterBehavior:を使って設定でき、引数にNSDateFormatterBehavior10_4を渡したsetFormatterBehavior:を使ってインスタンスの動作を設定できます。

デフォルトでは、10.4-スタイルのformatterはNSDateオブジェクト(Mac OS X v10.4以前の場合、date formattersはNSCalendarDateオブジェクト)を返します。

この動作はsetGeneratesCalendarDates:を使って変更できますが、(特にMac OS X v10.6以降でのNSCalendarDateは)強く勧めません。



参考文献

NSTimer Class Reference

NSDate Class Reference

NSDateFormatter Class Reference

Cocoa Fundamentals Guide/Cocoaオブジェクト/クラスクラスタ

Wikipedia/グレゴリオ暦

基礎からのiOS SDK基礎からのiOS SDK
(2010/10/09)
鶴薗 賢吾、松浦 健一郎 他

商品詳細を見る






Bose QuietComfort 20
0 Comments
Leave a comment
管理者にだけ表示を許可する
Top
0 Trackbacks
Top
Calendar
08 | 2017/09 | 10
Sun Mon Tue Wed Thu Fri Sat
- - - - - 1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Recent Articles
iTunes


Swift
Categories
Tips
Profile

水月杏香

Author:水月杏香
永遠の初心者プログラマ。

Wish List
WACOM


ARC
Technical Q&A
情報プロパティリストキー
Start Developing iOS Apps Today
BOSE

Bose QuietComfort 20
Reference
NSApplicationDelegateプロトコル
NSArrayクラス
NSAutoreleasePoolクラス
NSBundleクラス
NSBundle UIKit追加分
NSCalendarクラス
NSCoderクラス
NSCodingプロトコル
NSCopyingプロトコル
NSDataクラス
NSDateクラス
NSDateFormatterクラス
NSDictionaryクラス
NSEntityDescriptionクラス
NSEnumeratorクラス
NSErrorクラス
NSExceptionクラス
NSFetchRequestクラス
NSFileHandleクラス
NSFileManagerクラス
NSIndexPathクラス
NSIndexPath UIKit追加分
NSKeyedArchiverクラス
NSKeyedUnarchiverクラス
NSKeyValueCodingプロトコル
NSLocaleクラス
NSManagedObjectクラス
NSManagedObjectContextクラス
NSManagedObjectModelクラス
NSMutableArrayクラス
NSMutableCopyingプロトコル
NSMutableDictionaryクラス
NSMutableSetクラス
NSNotificationクラス
NSNotificationCenterクラス
NSNullクラス
NSNumberクラス
NSObjectクラス
NSObject UIKit追加分
NSObjectプロトコル
NSPersistentStoreクラス
NSPersistentStoreCoordinatorクラス
NSPredicateクラス
NSPropertyListSerializationクラス
NSRunLoopクラス
NSSetクラス
NSStringクラス
NSString UIKit追加分
NSTimerクラス
NSTimeZoneクラス
NSURLクラス
NSURLProtectionSpaceクラス
NSURLRequestクラス
NSUserDefaultsクラス
NSValueクラス

UIActionSheetクラス
UIActionSheetDelegateプロトコル
UIActivityIndicatorViewクラス
UIAlertViewクラス
UIAlertViewDelegateプロトコル
UIApplicationクラス
UIApplicationDelegateプロトコル
UIBarButtonItemクラス
UIBarItemクラス
UIButtonクラス
UIColorクラス
UIControlクラス
UIDatePickerクラス
UIDeviceクラス
UIEventクラス
UIFontクラス
UIGestureRecognizerクラス
UIImageクラス
UIImageViewクラス
UIKit Function
UILabelクラス
UINavigationControllerクラス
UINavigationItemクラス
UIPickerViewクラス
UIPickerViewDataSourceプロトコル
UIPickerViewDelegateプロトコル
UIPinchGestureRecognizerクラス
UIResponderクラス
UIScreenクラス
UIScrollViewクラス
UISearchBarクラス
UISearchBarDelegateプロトコル
UISegmentedControlクラス
UISliderクラス
UISwipeGestureRecognizerクラス
UISwitchクラス
UITableViewクラス
UITableViewCellクラス
UITableViewControllerクラス
UITableViewDataSourceプロトコル
UITableViewDelegateプロトコル
UITapGestureRecognizerクラス
UITextFieldクラス
UITextFieldDelegateプロトコル
UITextInputTraitsプロトコル
UITextViewクラス
UITextViewDelegateプロトコル
UIToolbarクラス
UITouchクラス
UIViewクラス
UIViewControllerクラス
UIWebViewクラス
UIWebViewDelegateプロトコル
UIWindowクラス

AVAudioPlayerクラス
AVAudioPlayerDelegateプロトコル

CADisplayLinkクラス
CAEAGLLayerクラス
CALayerクラス

CGAffineTransform
CGBitmapContext
CGColor
CGColorSpace
CGContext
CGGeometry
CGImage
CGPath

EAGLContextクラス
EAGLDrawableプロトコル

Foundation Constants
Foundation Data Types
Foundation Functions

MPMediaItemクラス
MPMediaItemArtworkクラス
MPMediaPlaylistクラス
MPMediaPropertyPredicateクラス
MPMediaQueryクラス
MPMusicPlayerControllerクラス

Randomization Services

System Sound Services
Amazon


OpenGL ES
SQLite
Monthly Archives
Recent Comments
Recent TrackBacks
RSS Link
Visitors
QR Code
QR