2

我正在实现一个应用程序,其中一个类的实例以及类本身都有“孩子”(放置在 a 内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[MyClass class]然后,您可以遍历John Calsbeek 提到的。

//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:,那将不适用于类对象,因为有 a +conformsToProtocol:,它具有不同的含义。他们可能不得不使用运行时函数或特殊情况的类对象。)例如,NSDictionary文档说它的键必须符合NSCopying,但是如果你有一个不符合NSCopying但确实实现的对象copyWithZone:,它可以正常工作。(其实有一个+copyWithZone:方法,其声明的目的是允许将类对象用作字典键,因此很明显,键不需要显式地符合NSCopying.)

于 2012-08-24T22:54:07.900 回答