2012-08-24 173 views
2

注意:解释起来相当复杂。请在这一个裸露与我。快速枚举类对象

大家嗨,

我执行的应用程序,其中一类的两个实例以及类本身有“孩子”(放在里面NSMutableArray)。这是一个相当复杂的应用程序,但是感谢Objective-C,它很容易:类本身就是对象,可以有方法和“变量”(借助于静态变量等)。为了让自己变得容易,我对两个实例(使用-)和类(使用+)实施accessor/setter方法来获取和操作“子”,而无需直接访问数组。我喜欢尽可能地关闭我的对象,并且这些方法会进行一些数据验证。

我也从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文件,实现快速列举宏,其中申明上面是偷看可能,但我不确定苹果是否也这样做。

即使我不能将NSFastEnumeration协议与我的类对象相关联,是否可以快速枚举而不使用该协议(以及未来验证)?

谢谢。

回答

3

方法-countByEnumeratingWithState:objects:count:是整个快速枚举 - 我相信这个协议主要是为了描述(实现协议比用正确的签名声明方法更容易)。我希望它能够正常工作,但我没有这方面的参考。不过,你可能想循环使用[MyClass class]

我会大概认为它面向未来。请注意,在你的类对象周围制作一个很小的包装类,除了实现NSFastEnumeration并将实例方法-countByEnumeratingWithState:objects:count:转发到你的类的方法+countByEnumeratingWithState:objects:count:之外,其实是微不足道的。

1

我建议使用与NSFastEnumeration方法相同的类方法创建一个协议。然后你可以迭代[MyClass class]作为John Calsbeek mentioned

//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); 
    } 
... 
1

我可以......?

那么,你试过吗?它工作吗?如果你已经尝试过了,你会注意到它确实可以编译和工作。

为什么不呢?类对象就像其他对象一样是对象。类方法只是碰巧在类对象上的方法。如果您将消息发送给类对象,它将调用类方法;而如果您向非类对象发送消息,则会调用实例方法。所以,您可以将类方法放在类上,并使用类对象,就像您可以通过将实例方法放在类中一样使用普通对象一样。

唯一可能的区别是类对象不会明确地符合NSFastEnumeration协议,类似于如果您循环访问其类没有明确指定它符合NSFastEnumeration协议的普通对象。所以问题是,它们在使用它之前是否明确地符合协议(而不是检查它是否响应选择器)?根据我的经验,对于几乎所有Cocoa来说,对于那些声称它们需要符合协议的对象的API,您可以给出一个对象,该对象不明确地符合协议,但实现了所有协议的方法,它会正常工作。 (他们如何检查它?如果它们使用conformsToProtocol:,那么对于类对象将不起作用,因为有一个+conformsToProtocol:,它具有不同的含义,可能必须使用运行时函数或特例类对象。)例如,NSDictionary文档说它的密钥必须符合NSCopying,但是如果您有一个对象不符合NSCopying,但确实实现了copyWithZone:,它工作正常。 (实际上,有一个+copyWithZone:方法,其陈述的目的是允许类对象用作字典键,所以显然它的意图是键不需要明确符合NSCopying。)

+0

它确实工作,但我想知道它是否能够适应未来。但就像你说的,即使不符合协议,它可能是好的...并且会保持如此。 –