9

いくつかのオブジェクトコンポジションを持つモデルクラスがありますが、このためのイテレータを作成するための最良の方法がわかりません。問題をより詳細に確認するために、階層(半擬似コード)を次に示します。

ルートクラス:

MYEntity : NSObject
@property int commonProperty;
@property NSArray *childs; //Childs of any kind.

いくつかの具体的なサブクラス:

MYConcreteStuff : MYEntity
@property int number;

MYConcreteThing : MYEntity
@property NSString *string;

そして、具体的なコレクションを持つルートオブジェクト:

MYRoot : MYEntity
@property MYEntity *stuff; //Collect only stuff childs here.
@property MYEntity *things; //Collect only thing childs here.

これで、次のように、コレクションのクールなメンバーアクセサーを(MYEntityで)作成できます。

-(MYEntity*)entityForIndex:(int) index
{
    if ([self.childs count] > index)
        return [self.childs objectAtIndex:index];

    return nil;      
}

そして、ルートオブジェクト用のさらにクールで適切なタイプのキャストメンバーアクセサー。

-(MYConcreteThing*)thingForIndex:(int) index
{
    if ([self.things count] > index)
        return (MYConcreteThing*)[self.things entityForIndex];

    return nil;    
}

しかし、私はそのようなコレクションのためにいくつかのワンライナーイテレーターを書く方法がわかりません。志望のクライアントコードは次のようなものです。

for (MYConcreteThing *eachThing in myRoot.things)
  eachThing.string = @"Success."; //Set "thingy" stuff thanks to the correct type.

私はブロックを使用することを考えていますが、よりクリーンなカットソリューションがあるかもしれません。何かアイデア/経験はありますか?

4

2 に答える 2

8

ここでは、ブロックについて説明します。これは非常に簡単です。今、私は列挙という用語を好みます。

ものを列挙するためのブロック型 (正しい型を保証する):

typedef void (^MYThingEnumeratorBlock)(MYThing *eachThing);

MYRoot 内の Thing のクールな列挙子メソッド (コレクションを公開しないため):

-(void)enumerateThings:(MYThingEnumeratorBlock) block
{    
    for (MYThing *eachThing in self.things.childs)
        block(eachThing);
}

したがって、クライアント コードは次のようになります。

[myRoot enumerateThings:^(MYThing *eachThing)
 {
    NSLog(@"Thing: %@", eachThing.string);         
 }];

きちんとしたマクロを使って:

#define ENUMARATE_THINGS myRoot enumerateThings:^(MYThing *eachThing)

[ENUMARATE_THINGS
{
   NSLog(@"Thing: %@", eachThing.string); //Cool "thingy" properties.        
}];
于 2012-09-23T13:09:30.853 に答える
1

私の意見では、これを行うための最良の方法は、配列プロパティにKeyValueCoding準拠のメソッドを実装することです。これには、コレクションを他のオブジェクトで観察できるようにするという追加のボーナスがあります。あなたはそれについてのすべてをアップルのドキュメントで読むことができます。MYRootクラスのThings配列の実装例を次に示します。各メソッドのコードを自由にパーソナライズしてください。

// KVC method for read-only array of Things
- (NSUInteger) countOfThings
{
    return _things.count;
}

- (Thing*) objectInThingsAtIndex:(NSUInteger)index
{
    return [_things objectAtIndex:index];
}

// Additional KVC methods for mutable array collection
- (void) insertObject:(Thing*)thing inThingsAtIndex:(NSUInteger)index
{
    [_things insertObject:thing atIndex:index];
}

- (void) removeObjectInThingsAtIndex:(NSUInteger)index
{
    [_things removeObjectAtIndex:index];
}

コレクションを反復処理するには、次のようにします。

for (Thing *thing in [_entity valueForKey:@"things"]) {
}

配列にThingを追加するには、次のようにします。

NSMutableArray *children = [_entity mutableArrayValueForKey:@"things"];
[children addObject:aThing];

このようにすることで、@"things"プロパティを監視しているすべてのオブジェクトに、配列に対するすべての変更が通知されるようになります。挿入メソッドを直接呼び出すと、呼び出されません(これはそれ自体で役立つ場合があります)。

于 2012-09-23T05:06:48.110 に答える