刚在Mikeash的博客上发现了苹果实现快速枚举的思路,详情。
虽然没太看懂是什么意思,但大概思路是把集合一块块取出(而不是一个个取出),在每一块中再进行枚举。快速枚举协议(NSFastEnumeration)
- (NSUInteger)countByEnumeratingWithState: (NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len;
有个struct
typedef struct {
unsigned long state;
id *itemsPtr;
unsigned long *mutationsPtr;
unsigned long extra[5];
}
介绍下这个struct.
- state 描述当前collection循环的状态,可能是continue,可能是break
- itemPtr 当前取出块(bulk)collection对象pointer的c array.
- mutationPtr 快速枚举有个功能就是能检测出枚举的时候乱改collection的值,这是不允许的,但它能给出警告。
- extra[5] i dont have a idea.
所以说,Objc 的
for(id obj in collection)
{
// body
}
如何实现呢?
见下,
// declare all the local state needed
NSFastEnumerationState state = { 0 };
id stackbuf[16];
BOOL firstLoop = YES;
long mutationsPtrValue;
// outer loop
NSUInteger count;
while((count = [collection countByEnumeratingWithState: &state objects: stackbuf count: 16]))
{
// check for mutation, but only after the first loop
// (note that I'm not sure whether the real compiler puts this
// in the inner loop or outer loop, and it could conceivably
// change from one compiler version to the next)
if(!firstLoop && mutationsPtrValue != *state.mutationsPtr)
@throw ..mutation exception...
firstLoop = NO;
mutationsPtrValue = *state.mutationsPtr;
// inner loop over the array returned by the NSFastEnumeration call
id obj;
for(NSUInteger index = 0; index < count; index++)
{
obj = state.itemsPtr[index];
// body
}
}
可以看懂的是,这里面的双重循环。从collection里一块块取,再在块里面一个个枚举。