クロックに独自クラスを導入する(2)

2010. 06. 02
Clockクラスの実装の話の前に、NSObjectの説明をしたいと思います。


●NSObjectクラス

NSObjectは、ほとんどのObjective-Cクラスのヒエラルキー(階層)のルートクラスです。

NSObjectを通して、オブジェクトはランタイムシステムの基本インターフェイスと、Objective-Cオブジェクトとして動作する能力を引き継ぎます。


●initメソッドの実装

Clock.hで宣言したメソッドを実装する前に、Clockクラスの初期化メソッドとしてinitメソッドを記述します。

これは、Clockクラスのインスタンス生成・初期化時にinitメソッドを呼び出した場合、(Clockクラス内でinitメソッドをオーバーライドしないと)スーパークラスであるNSObjectのinitメソッドが呼び出されてしまい、インスタンス変数であるtimerとtimeZoneが初期化されないので、オーバーライドする必要があるためです。
(太字が追加した部分)

#import <Foundation/Foundation.h>

@implementation Clock

- (id)init {
    // スーパークラスによる初期化
    self = [super init];

    if (self != nil) {
        // timerの生成
        timer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(updateClock:) userInfo:nil repeats:YES];

        // timerZoneの生成
        timeZone = [[NSTimeZone systemTimeZone] retain];
    }

    // 初期化したインスタンスを返す
    return(self);
}
 

@end

360

まず最初にスーパークラスによる初期化を行います。

これは、元となるスーパークラスで初期化できる部分をしてもらうことで、残りは独自に宣言したインスタンス変数のみ初期化すればいいという状態にするためです。

スーパークラスのメソッドを呼び出すには、ターゲットをsuperに指定します。

従って『self = [super init];』は、(Clockクラスのインスタンスオブジェクト)自身をスーパークラス(NSObject)のinitメソッドで初期化することになります。

『if (self != nil)』はinitメソッドによる初期化の可否を判定し、初期化が成功した場合は{}内の処理を行います。

初期化が成功した場合は、timerとtimerZoneの初期化を行います。

timerの生成は元と同じなので、『クロックのメソッド』を参照してください。

timeZoneの生成は、systemTimeZoneで現在システムで設定されているタイムゾーンを取得し、リファレンスカウンタをretainで1増やして呼び出したメソッドと共有できるようにします。

リファレンスカウンタは参照カウンタや保持カウンタとも呼ばれ、インスタンスが確保した値を共有するためのものです。
(詳細は『基礎からのiPhone SDK 改訂版』や、詳しくない『Objective-C言語のメモ書き(1)』、『Objective-C言語のメモ書き(7)』などを参照してください)

最後に初期化したインスタンスを返します。


・init
(NSObjectクラス)

- (id)init

サブクラスの実装で、(レシーバの)新しいオブジェクトのメモリを割り当てた直後に初期化を行います

戻り値は、初期化したレシーバになります。

initメッセージは一般的にコードの同じ行の中でallocまたはallocWithZone:メッセージと組み合わせます

TheClass *newObject = [[TheClass alloc] init];

オブジェクトは初期化するまで使用する準備はできていません

initメソッドは、NSObjectクラスで定義されていない部分は初期化せず、単にselfを返します

サブクラスでこのメソッドを実行すると、新しいオブジェクトを初期化して返します

初期化できなかった場合、オブジェクトを解放してnilを返します

initメソッドは新しいオブジェクトを解放し、代替を返す場合もあります

したがって、プログラムはinitにより返されるオブジェクトを常に使うので、必ずしもallocまたはallocWithZone:の戻り値を使用したコードを続いて記述する必要はありません

全てのクラスはinitメソッドによって、完全に機能するクラスのインスタンスを返すか、または例外を発生させるかを保証する必要があります

サブクラスは、追加するクラス定義の初期化コードで、initメソッドをオーバーライドする必要があります

サブクラスは、superにメッセージを渡してクラスを継承するために、initを含む初期化コードを必要とします

- (id)init
{
    self = [super init];
    if (self) {
        /* class-specific initialization goes here */
    }
    return self;
}

メソッドのクラスの初期化コードの前に、superへのメッセージを追加してください

この順序で、継承を受けた初期化を確実に続けることができます

サブクラスは、しばしば特定の値を引数として加えたinit~メソッドで定義されます

メソッドの引数が多いと、初期化するオブジェクトの特徴により多くの自由を与えます

クラスは、しばしばinit~メソッドの設定で引数の数が異なることがあります

例えば、

- (id)init;
- (id)initWithTag:(int)tag;
- (id)initWithTag:(int)tag data:(struct info *)data;

規則では少なくともこれらのメソッドの内の一つは、たいてい一つの引数を持ち、より高い階層のクラスでの初期化である、superへのメッセージに組み込まれます

このメソッドは、クラスの『指定イニシャライザ』と呼ばれます

クラスでの他のinit~メソッドの定義は、直接または間接的に指定イニシャライザを呼び出し、selfにメッセージを渡します

この方法では、全てのinit~メソッドはひとまとめに繋げます

- (id)init
{
    return [self initWithTag:-1];
}

- (id)initWithTag:(int)tag
{
    return [self initWithTag:tag data:NULL];
}

- (id)initWithTag:(int)tag data:(struct info *)data
{
    self = [super init. . .];
    if (self) {
        /* class-specific initialization goes here */
    }
    return self;
}

この例では、initWithTag:data:メソッドがクラスの指定イニシャライザです

サブクラスで独自の初期化をしない場合は、独自の指定イニシャライザを定義する必要があります

このメソッドは、スーパークラスの指定イニシャライザを呼び出して、superにメッセージを送ります

仮に例えば、上記の3つのメソッドをBクラスで定義したとします

CクラスはBのサブクラスで、この指定イニシャライザを持っているとします

- (id)initWithTag:(int)tag data:(struct info *)data object:anObject
{
    self = [super initWithTag:tag data:data];
    if (self) {
        /* class-specific initialization goes here */
    }
    return self;
}

継承したinit~メソッドがサブクラスのインスタンスを正常に初期化した場合、新しい指定イニシャライザを(直接または間接的に)呼び出さなければなりません

これを遂行するには、サブクラスはサブクラスの指定イニシャライザをオーバーライドしなければなりません

例えば、Cクラスに指定イニシャライザを追加するには、次のような実装になります

- (id)initWithTag:(int)tag data:(struct info *)data
{
    return [self initWithTag:tag data:data object:nil];
}

このコードは、Bクラスから3つ全てのメソッドを継承した、Cクラスのインスタンスにも同様に作用することを保証します

サブクラスの指定イニシャライザは、しばしばスーパークラスの指定イニシャライザをオーバーライドします

その場合、サブクラスは一つのinit~メソッドを実装するだけで済みます

これらの規則は、init~との直接な関連のリンクを保持し、newメソッドと継承した全てのinit~メソッドが、使用可能な初期化したオブジェクトを確実に返します

また無限ループの可能性を防ぐため、サブクラスメソッドはsuperにメッセージを送ってスーパークラスメソッドを実行し、折り返しselfに送られたメッセージをサブクラスメソッドが実行します

このinitメソッドは、NSObjectクラスの指定イニシャライザです

サブクラスが独自の初期化をする場合は上記のようにオーバーライドします


・systemTimeZone
(NSTimeZoneクラス)

+ (NSTimeZone *)systemTimeZone

現在システムで使われているタイムゾーンを返します

現在のタイムゾーンが取得できない場合は、グリニッジ標準時(GMT)を返します

システムのタイムゾーンを取得する場合、アプリケーションによってキャッシュされるため、ユーザがその後でシステムのタイムゾーンを変更しても更新されません

したがってsystemTimeZoneを再び呼び出しても、最初に取得したタイムゾーンと同じものになります

アプリケーションのキャッシュをクリアするにはresetSystemTimeZoneを呼び出してください



参考文献

NSObject Class Reference

NSTimeZone Class Reference

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

商品詳細を見る

詳解 Objective-C 2.0 第3版詳解 Objective-C 2.0 第3版
(2011/12/28)
荻原 剛志

商品詳細を見る






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