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
}