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ランタイムを出すなどの対応は欲しいところだ。