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 中事物的一种很酷的枚举器方法(不公开集合):

-(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

在我看来,最好的方法是为数组属性实现符合键值编码的方法。这将有额外的好处,使您的集合可以被其他对象观察到。您可以在苹果文档中阅读所有相关信息。这是 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"]) {
}

要在数组中添加一个东西,你可以做

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

这样做可以确保所有观察该@"things"属性的对象都将收到有关数组所有更改的通知。如果您直接调用插入方法,它们不会(这有时本身很有用)。

于 2012-09-23T05:06:48.110 回答