Fast Enmeration

Fast Enumerationも、他言語にある機能を取り入れた形だ。

Cocoaでの繰り返しの記述は、NSEnumeratorを使っていた。Objective-C 1.0では、次のようなコーディングを行っていた。

NSArray* names = [NSArray arrayWithObjects:@"iPhone", @"iPod touch", @"iPod nano", nil];

NSEnumerator* enumerator;
NSString*     name;
enumerator = [names objectEnumerator];
while (name = [enumerator nextObject]) {
    ...
}

まずNSEnumeratorのインスタンスを取得し、while文を回している。これが、Objective-C 2.0では次のようにコーディングすることが可能になる。

NSArray* names = [NSArray arrayWithObjects:@"iPhone", @"iPod touch", @"iPod nano", nil];

for (NSString* name in names) {
    ...
}

このように、for文の記法が拡張された。今まではNSEnumeratorの変数を宣言しなくてはいけなかったのだが、それは必要なくなり、かつ繰り返しに使う変数もfor文の中でも宣言出来るようになっている。

とにかく、コーディングの量が減ったのが嬉しいところだ。for - inという記法も、今までのObjective-Cにはなかったものだが、個人的には違和感なく使える。一度使うと、Objective-C 1.0に戻れなくなってしまう便利さだ。

NSFastEnumerationプロトコル

NSEnumeratorでは、そのコレクションクラスがNSEnumeratorプロトコルに準拠したインスタンスを作成していた。Objective-C 2.0では、Fast Enumerationのために、新しいプロトコルを導入している。NSFastEnumerationだ。

NSFastEnumerationに準拠するために実装しなくてはいけないメソッドは、1つである。countByEnumeratingWithState:objects:count:である。

@protocol NSFastEnumration
- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState*)state objects:(id*)stackbuf count:(NSUInteger)len;
@end

Leopardでは、NSEnumeratorがこのNSFastEnumerationに準拠しているため、NSEnumeratorを作成出来るクラスならば、Fast Enumerationの記法が使えることになる。だが、効率的な繰り返しを行うには、このメソッドを直接実装する必要があるだろう。

その他の変更点

言語仕様以外にも、ランタイムに大きな変更が加えられた。これについては、「Objective-C 2.0 Runtime Reference: Mac OS X Version 10.5 Delta」を参照してほしい。多くの関数が追加され、数個の関数が変更され、そしていくつかの関数がdeprecated、つまり推奨されないものとなった。

推奨されなくなったメソッドのうち、個人的に注目したいのは、class_poseAsだ。これはポージングを行うもので、長らくCocoaのハックに大活躍していたクラスだ。

この関数が使えなくなるということは、AppleはCocoaのハックを押さえ込もうとしているのかという考えが、一瞬よぎった。だがさにあらず、その代わりにmethod_exchangeImplementaionsという関数が追加されたのだ。この関数の使い方は、こちらのサンプルを参照してほしい。これでは、ポージングとまったく同じことができてしまうではないか。というよりは、クラスの継承も無くなった分、さらに便利にハックができてしまうではないか。

時代が、セキュリティの必要性をややもすると過剰気味に叫ぶ中、おおらかというか、ハッカー好みなAppleの方針ではないだろうか。

これから始めるには最適、移行もある程度考慮

こうして変更点を並べてみると、プログラミングを始める敷居が低くなったのを感じる。

その最たるものは、何と言ってもガベージコレクションだ。煩雑なメモリ管理の方法を覚える必要なしで、プログラミングを始めることができるようになったのは大きい。プロパティも、Fast Enumerationも、コーディングの量が減った分、書き易く覚え易くなったと言えるだろう。

反面、すでにObjective-C 1.0のソースコードを大量に書いている場合は、移行のタイミングを測る必要がある。もっとも、1.0と2.0の併存も出来るので、それほど重大な問題にはならないかもしれない。ただし、Objective-C 2.0で書いたものは、Tiger以前のものでは動かせなくなる。この過去のOSの、潔いというか容赦ない切り捨て方は、いつものAppleのやり方ではあるが、本気でObjective-Cの普及を考えているならば、Tiger用のObjective-C 2.0ランタイムを出すなどの対応は欲しいところだ。