2

クラスのインスタンスとクラス自体の両方に「子」があるアプリケーションを実装しています( 内に配置されていますNSMutableArray)。これはかなり複雑なアプリケーションですが、Objective-C のおかげでとても簡単です。クラスはそれ自体がオブジェクトであり、メソッドと「変数」を持つことができます (静的変数などの助けを借りて)。

簡単にするために、インスタンス ( を使用-) とクラス ( を使用) の両方にアクセサー/セッター メソッドを実装+して、配列に直接アクセスせずに「子」を取得して操作しました。オブジェクトを可能な限り閉じて、メソッドでデータ検証を行うようにしています。

また、プロトコルから高速列挙インスタンスメソッドを実装しました。ここで質問があります。高速な列挙型クラスNSFastEnumerationメソッドを実装して、それを Objective-C のコンストラクトで使用できますか? つまり、これを実装できますか:for...in

+ (NSUInteger)countByEnumeratingWithState: (NSFastEnumerationState *)state objects: (__unsafe_unretained id [])buffer count: (NSUInteger)len;

そして、そのような場所で使用します:

for (id child in [MyClass class]) {
    // Do magic stuff…
}

マクロとして高速な列挙を実装する GNUStep のGSFastEnumeration.hファイルを覗いてみたところ、上記が可能であることが確認されましたが、Apple が同じことを行っているかどうかはわかりません。

プロトコルを自分のクラス オブジェクトに関連付けることができなくても、NSFastEnumerationそのプロトコルを使用せずに高速な列挙を行うことはできますか (そして将来的に保証されますか)?

4

3 に答える 3

3

メソッド-countByEnumeratingWithState:objects:count:は高速列挙の全体です。プロトコルは、ほとんどが説明のためにあると思います (正しい署名でメソッドを宣言するよりも、プロトコルを実装する方が簡単です)。うまく機能すると思いますが、そのための参照はありません。ただし、おそらくループしたいと思うでしょう[MyClass class]

私はおそらくそれを将来の保証と見なすでしょう。NSFastEnumerationインスタンスメソッド-countByEnumeratingWithState:objects:count:を実装してクラスのメソッドに転送するだけのクラスオブジェクトの周りに小さなラッパークラスを作成するのは本当に簡単なこと+countByEnumeratingWithState:objects:count:です。

于 2012-08-24T14:23:54.323 に答える
1

メソッドと同じクラス メソッドを持つプロトコルを作成することをお勧めしますNSFastEnumerationその後、 John Calsbeek が述べ[MyClass class]たように を反復処理できます。

//Protocol implementation
@protocol FastClassEnumeration <NSObject>
@required
+ (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id [])buffer count:(NSUInteger)len;
@end

//Class implementation
@interface EnumeratedClass : NSObject<FastClassEnumeration>
@end
@implementation EnumeratedClass

+ (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id [])buffer count:(NSUInteger)len
{
    static const unsigned long items_length = 4;
    static NSString * items[items_length] = { @"item1", @"item2", @"item3", @"item4" };

    if(state->state >= items_length)
    {
        return 0;
    }

    state->itemsPtr = items;
    state->state = items_length;
    state->mutationsPtr = (unsigned long *)self;

    return items_length;
}

@end

//Usage
...
    for(NSString *item in [EnumeratedClass class])
    {
        NSLog(@"%@", item);
    }
...
于 2012-08-24T14:47:37.563 に答える
1

私は...できますか?

さて、あなたはそれを試しましたか?それは機能しますか?試してみると、実際にコンパイルして動作することがわかります。

そして、なぜそうすべきではないのですか?クラス オブジェクトは、他のオブジェクトと同様のオブジェクトです。クラスメソッドは、たまたまクラスオブジェクトにあるメソッドです。クラス オブジェクトにメッセージを送信すると、クラス メソッドが呼び出されます。一方、非クラス オブジェクトにメッセージを送信すると、インスタンス メソッドが呼び出されます。つまり、クラスにクラス メソッドを配置し、そのクラスにインスタンス メソッドを配置することで通常のオブジェクトを使用するのと同じように、クラス オブジェクトを使用できます。

唯一の違いは、クラス オブジェクトがプロトコルに明示的に準拠してNSFastEnumerationいないことです。これは、クラスがプロトコルに準拠していることを明示的に指定していない通常のオブジェクトをループする場合と同様NSFastEnumerationです。問題は、オブジェクトを使用する前に、オブジェクトがプロトコルに明示的に準拠していることを確認しますか (セレクターに応答するかどうかを確認するのではなく)。

私の経験では、ほぼすべての Cocoa について、プロトコルに準拠するオブジェクトが必要であると言う API については、プロトコルに明示的に準拠していないが、プロトコルのすべてのメソッドを実装するオブジェクトを指定できます。うまく動作します。(とにかくどうやってチェックするのでしょうか? を使用すると、別の意味を持つconformsToProtocol:が存在するため、クラス オブジェクトに対しては機能しません+conformsToProtocol:。実行時関数または特殊なケースのクラス オブジェクトを使用する必要があるでしょう。) たとえば、NSDictionaryドキュメントには、そのキーが に準拠する必要があると記載されていますが、 に準拠していないが実装NSCopyingしているオブジェクトがある場合、それは正常に機能します。(実際には、NSCopyingcopyWithZone:+copyWithZone:メソッドの目的は、クラス オブジェクトを辞書のキーとして使用できるようにすることです。そのため、キーが明示的に に準拠する必要がないことは明らかですNSCopying。)

于 2012-08-24T22:54:07.900 に答える