Objective-C 中的快速枚举与 NSEnumerator

发布于 2024-10-20 00:23:30 字数 95 浏览 4 评论 0原文

我已经一遍又一遍地看到这一点,为什么在循环中使用快速枚举比使用 nextObject:NSEnumerator 更快。

I have seen this over and over, why exactly is it faster to use fast enumeration in loops rather than an NSEnumerator using nextObject:.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

何以心动 2024-10-27 00:23:30

NSEnumerator 是枚举集合的旧方法。它涉及创建一个对象来表示枚举,然后为每次迭代调用该对象的方法。虽然这多年来一直可以完美使用,但它的效率并不是很高,因为它涉及到为循环的每次迭代发送至少一条消息。 < code>NSFastEnumeration 是更现代的方法,它利用本机语言支持来提供更有效的枚举。它在底层的工作方式是创建一个表示当前枚举状态的结构并重复调用 -countByEnumerationWithState:objects:count: 在集合上。此方法在 objects 输出参数中返回一个 C 对象数组,并在 count 输出参数中返回一个计数器。这允许调用者迭代 C 数组。本质上,这意味着每个对象块一次消息调用,根据集合的不同,这可能与获取所有对象的单个消息调用一样高效。

如果你有一些看起来像

for (id obj in myArray) {
    [obj doSomething];
}

这样的代码,编译器会将其翻译成大致相当于

NSFastEnumerationState __enumState = {0};
id __objects[MAX_STACKBUFF_SIZE];
NSUInteger __count;
while ((__count = [myArray countByEnumeratingWithState:&__enumState objects:__objects count:MAX_STACKBUFF_SIZE]) > 0) {
    for (NSUInteger i = 0; i < __count; i++) {
        id obj = __objects[i];
        [obj doSomething];
    }
}

使用的实际变量是隐藏的,并且对象缓冲区的最大大小也取决于实现,但基本思想是存在的。它将 obj-c 集合上的迭代转换为 C 数组上的迭代。

NSEnumerator is the old way to enumerate over collections. It involves creating an object to represent the enumeration, then calling a method on it for every single iteration. While this was perfectly serviceable for many years, it's not terribly efficient, as it involves at least one message send for every iteration of the loop. NSFastEnumeration is the more modern approach, which leverages native language support to provide a much more efficient enumeration. The way it works under the hood is it creates a struct that represents the current enumeration state and repeatedly calls -countByEnumeratingWithState:objects:count: on the collection. This method returns a C array of objects in the objects out-param as well as a counter in the count out-param. This allows the caller to then iterate over the C array. In essence, this means one message call per chunk of objects, which, depending on the collection, could be as efficient as a single message call to get all objects.

If you have a bit of code that looks like

for (id obj in myArray) {
    [obj doSomething];
}

This gets translated by the compiler into something roughly equivalent to

NSFastEnumerationState __enumState = {0};
id __objects[MAX_STACKBUFF_SIZE];
NSUInteger __count;
while ((__count = [myArray countByEnumeratingWithState:&__enumState objects:__objects count:MAX_STACKBUFF_SIZE]) > 0) {
    for (NSUInteger i = 0; i < __count; i++) {
        id obj = __objects[i];
        [obj doSomething];
    }
}

The actual variables used are hidden, and the maximum size of the object buffer is also implementation-dependent, but the basic idea is there. It translates iteration over an obj-c collection into iteration over a C array.

神回复 2024-10-27 00:23:30

不一样作为苹果的实现,但它有助于理解。

- (NSUInteger) countByEnumeratingWithState: (NSFastEnumerationState*)state  
                   objects: (id*)stackbuf
                     count: (NSUInteger)len
{
  IMP nextObject = [self methodForSelector: @selector(nextObject)];
  int i;

  state->itemsPtr = stackbuf;
  state->mutationsPtr = (unsigned long*)self;
  for (i = 0; i < len; i++)
    {
      id next = nextObject(self, @selector(nextObject));

      if (nil == next)
    {
      return i;
    }
      *(stackbuf+i) = next;
    }
  return len;
}

It is not same as Apple's implementation but it is helpful to understand.

- (NSUInteger) countByEnumeratingWithState: (NSFastEnumerationState*)state  
                   objects: (id*)stackbuf
                     count: (NSUInteger)len
{
  IMP nextObject = [self methodForSelector: @selector(nextObject)];
  int i;

  state->itemsPtr = stackbuf;
  state->mutationsPtr = (unsigned long*)self;
  for (i = 0; i < len; i++)
    {
      id next = nextObject(self, @selector(nextObject));

      if (nil == next)
    {
      return i;
    }
      *(stackbuf+i) = next;
    }
  return len;
}
鹿! 2024-10-27 00:23:30
NSArray *array = something;

数组 = { {1,2}, {2,3}, {3,4} }

表示数组是数组的数组。那么如何访问所有数组及其值。
我们可以像这样使用 for 循环

for (int i = 0; i < array.count; i++)
{
    NSArray x = [array objectAtIndex:i];
}

,或者像这样使用快速枚举,

for(NSArray array2 in array)
{
   // do what ever you want with this new array2.
}

这是一个示例示例。
附言。我忘记了数组在控制台中的样子。

NSArray *array = something;

array = { {1,2}, {2,3}, {3,4} }

that means array is an array of array. so how can you access all the arrays and their values.
we can use for loop like this

for (int i = 0; i < array.count; i++)
{
    NSArray x = [array objectAtIndex:i];
}

or a fast enum works like this

for(NSArray array2 in array)
{
   // do what ever you want with this new array2.
}

this is a sample example.
PS. I forgot how the array looks in console.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文