objective-c - logo - what is apache hbase




Como faço para iterar em um NSArray? (6)

Adicione each método na sua NSArray category , você vai precisar muito

Código retirado do ObjectiveSugar

- (void)each:(void (^)(id object))block {
    [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        block(obj);
    }];
}

Eu estou procurando o idioma padrão para iterar sobre um NSArray. Meu código precisa ser adequado para o OS X 10.4+.


Aqui está como você declara uma matriz de strings e itera sobre elas:

NSArray *langs = @[@"es", @"en", @"pt", @"it", @"fr"];

for (int i = 0; i < [langs count]; i++) {
  NSString *lang = (NSString*) [langs objectAtIndex:i];
  NSLog(@"%@, ",lang);
}

Faça isso :-

for (id object in array) 
{
        // statement
}

O código geralmente preferido para 10.5 + / iOS.

for (id object in array) {
    // do something with object
}

Essa construção é usada para enumerar objetos em uma coleção que esteja de acordo com o protocolo NSFastEnumeration . Essa abordagem tem uma vantagem de velocidade porque armazena ponteiros para vários objetos (obtidos por meio de uma única chamada de método) em um buffer e os percorre avançando pelo buffer usando a aritmética de ponteiros. Isso é muito mais rápido do que chamar -objectAtIndex: cada vez através do loop.

Também vale a pena notar que, embora tecnicamente você possa usar um loop for-in para percorrer um NSEnumerator , descobri que isso anula praticamente toda a vantagem de velocidade da enumeração rápida. O motivo é que a implementação padrão de NSEnumerator de -countByEnumeratingWithState:objects:count: coloca apenas um objeto no buffer em cada chamada.

Eu relatei isso no radar://6296108 (a enumeração rápida de NSEnumerators é lenta), mas ela foi retornada como Not To Be Fixed. O motivo é que a enumeração rápida pré-busca um grupo de objetos e se você deseja enumerar apenas um determinado ponto no enumerador (por exemplo, até que um objeto específico seja encontrado ou condição seja atendida) e usar o mesmo enumerador após sair do loop, muitas vezes seria o caso de vários objetos serem ignorados.

Se você está codificando para o OS X 10.6 / iOS 4.0 e acima, você também tem a opção de usar APIs baseadas em blocos para enumerar matrizes e outras coleções:

[array enumerateObjectsUsingBlock:^(id object, NSUInteger idx, BOOL *stop) {
    // do something with object
}];

Você também pode usar -enumerateObjectsWithOptions:usingBlock: e passar NSEnumerationConcurrent e / ou NSEnumerationReverse como o argumento de opções.

10.4 ou anterior

O idioma padrão para o pré-10.5 é usar um NSEnumerator e um loop while, da seguinte forma:

NSEnumerator *e = [array objectEnumerator];
id object;
while (object = [e nextObject]) {
  // do something with object
}

Eu recomendo mantê-lo simples. Amarrar-se a um tipo de array é inflexível, e o supostamente aumento de velocidade do uso de -objectAtIndex: é insignificante para a melhoria com enumeração rápida em 10.5+ de qualquer maneira. (A enumeração rápida, na verdade, usa a aritmética de ponteiros na estrutura de dados subjacente e remove a maior parte da sobrecarga da chamada do método.) A otimização prematura nunca é uma boa ideia - resulta em um código mais confuso para resolver um problema que não é seu gargalo.

Ao usar -objectEnumerator , você facilmente muda para outra coleção enumerável (como um NSSet , chaves em um NSDictionary , etc.), ou até mesmo alterna para -reverseObjectEnumerator para enumerar uma matriz de trás para frente, tudo sem outras alterações de código. Se o código de iteração estiver em um método, você pode até mesmo passar qualquer NSEnumerator e o código nem precisa se preocupar com o que está sendo iterativo. Além disso, um NSEnumerator (pelo menos aqueles fornecidos pelo código Apple) retém a coleção que está enumerando, desde que haja mais objetos, para que você não precise se preocupar com a duração de um objeto liberado automaticamente.

Talvez a maior coisa que um NSEnumerator (ou enumeração rápida) protege você é ter uma coleção mutável (matriz ou outra) mudar debaixo de você sem o seu conhecimento enquanto você o está enumerando. Se você acessar os objetos por índice, poderá encontrar exceções estranhas ou erros off-by (geralmente após o problema ter ocorrido) que podem ser horríveis para depuração. A enumeração usando uma das expressões padrão tem um comportamento "fail-fast", então o problema (causado por código incorreto) irá se manifestar imediatamente quando você tentar acessar o próximo objeto após a mutação ter ocorrido. À medida que os programas se tornam mais complexos e multiencadeados, ou até mesmo dependem de algo que um código de terceiros pode modificar, o código de enumeração frágil torna-se cada vez mais problemático. Encapsulamento e abstração FTW! :-)


Para Swift

let arrayNumbers = [11, 12, 13, 14, 15, 16, 17, 18, 19, 20]

// 1
for (index, value) in arrayNumbers.enumerated() {
    print(index, value)
    //... do somthing with array value and index
}


//2
for value in arrayNumbers {
    print(value)
    //... do somthing with array value
}

Para o OS X 10.4.xe anterior:

 int i;
 for (i = 0; i < [myArray count]; i++) {
   id myArrayElement = [myArray objectAtIndex:i];
   ...do something useful with myArrayElement
 }

Para o OS X 10.5.x (ou iPhone) e além:

for (id myArrayElement in myArray) {
   ...do something useful with myArrayElement
}




enumeration