遍历的目的是获取集合中的某个对象或执行某个操作,所以能满足这个条件的方法都可以作为备选:
- for
- for in
- enumerateObjectsUsingBlock
- enumerateObjectsWithOptions(NSEnumerationConcurrent)
更多方案请参考 iOS 中集合遍历方法的比较和技巧
NSArray *arr = @[@"0", @"1", @"3", @"4", @"6"];
经典 for 循环
for (int i = 0; i < [arr count]; i++) {
NSLog(@"%zi %@", i, arr[i]);
}
for in
for (NSString *string in arr) {
NSLog(@"%@", string);
}
enumerateObjectsUsingBlock
[arr enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSLog(@"%zi %@", idx, obj);
if ([obj isEqualToString:@"2"]) {
NSLog(@"------ %zi %@", idx, obj);
*stop = YES;
}
}];
enumerateObjectsWithOptions: usingBlock:
typedef NS_OPTIONS(NSUInteger, NSEnumerationOptions) {
NSEnumerationConcurrent = (1UL << 0),
NSEnumerationReverse = (1UL << 1),
Options 指定 NSEnumerationReverse 时 ,会进行倒叙排列;
Options 指定 NSEnumerationConcurrent 顺序,底层通过GCD来处理并发执行事宜,具体实现可能会用到dispatch group。也就是说,这个会用多线程来并发实现,并不保证按照顺序执行
[arr enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(id obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSLog(@"idx=%ld, id=%@", idx, obj);
//当需要结束循环的时候,调用stop,赋予YES
if (idx ==3) {
*stop = YES;
}
}];
NSArray 的两个方法:
reverseObjectEnumerator 也能实现倒叙排序
objectEnumerator 正序排序
for (NSString *string in [arr reverseObjectEnumerator]) {
NSLog(@"*-*-*- %@", string);
}
enumerateObjectsAtIndexes: options: usingBlock:
NSIndexSet 类代表一个不可变的独特的无符号整数的集合,称为索引,因为使用它们的方式。这个集合被称为索引集 唯一的,有序的,无符号整数的集合
- 索引集合的创建方式
[NSIndexSet indexSetWithIndex:1];//1.创建一个索引集合,根据索引值
[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0,8)];//2.创建一个索引集合,根据一个NSRange对象
- enumerateObjectsAtIndexes 使用方法
[arr enumerateObjectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0,3)] options:NSEnumerationReverse usingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSLog(@"\n\nidx=%ld, id=%@", idx, obj);
}];
遍历字典 key value
NSDictionary * dic = [NSDictionary dictionaryWithObjectsAndKeys:@"obj1",@"key1",@"obj2",@"key2", nil];
[dic enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) {
NSLog(@"dict >>> value for key %@ is %@ ", key, value);
if ([@"key2" isEqualToString:key]) {
NSLog(@"dict >>> %@ %@", key, value);
*stop = YES;
}
}];
对比
- for循环 、for in、和 EnumerateObjectsUsingBlock 的比较
- 对于集合中对象数很多的情况下,for in 的遍历速度非常之快,但小规模的遍历并不明显(还没普通for循环快)
- Value查询index的时候, 面对大量的数组推荐使用 enumerateObjectsWithOptions的并行方法.
- 遍历字典类型的时候, 推荐使用enumerateKeysAndObjectsUsingBlock,block版本的字典遍历可以同时取key和value(forin只能取key再手动取value)