2012-08-24 174 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

它確實工作,但我想知道它是否能夠適應未來。但就像你說的,即使不符合協議,它可能是好的...並且會保持如此。 –