数组的遍历有多种方式,这里介绍一下常见的方式,使用以及注意事项。
常用写法简介
1. 经典写法
1
2
3
4
5
6
7
8
9
| - (void) test:(NSArray*)array
{
NSInteger count = array.count;
for (NSInteger i = 0 ; i < count ; i ++ )
{
NSLog(@"%@",array[i]);
}
NSLog(@"end");
}
|
之所以使用count来存储数组总数,而不是写成 i < array.count ,是因为循环每进行一次都会调用数组的计数方法,这将导致性能变得很差。
2. NSEnumerator
1
2
3
4
5
6
7
8
9
10
| - (void) test:(NSArray*)array
{
id test = nil;
NSEnumerator* enumerator = [array objectEnumerator];
while (test = [enumerator nextObject])
{
NSLog(@"%@",test);
}
NSLog(@"end");
}
|
NSEnumerator的优势在于不需要知道数据总数,所以它适合应用在结构化数据上,比如链表,数据流等。
3. 快速枚举
1
2
3
4
5
6
7
8
| - (void) test:(NSArray*)array
{
for (NSString* test in array )
{
NSLog(@"%@",test);
}
NSLog(@"end");
}
|
快速枚举是apple推荐的方式,在使用上比经典的写法性能上更快。
使用上如果需要反向枚举,只需要将array改成array.reverseObjectEnumerator就可以了。
4. 枚举块
1
2
3
4
5
6
7
8
| - (void) test:(NSArray*)array
{
[array enumerateObjectsUsingBlock:^(NSString* obj, NSUInteger idx, BOOL *stop) {
NSLog(@"%@",obj);
}];
NSLog(@"end");
}
|
枚举块的优势在于它会返回对象和索引, 而其他的枚举方法只会返回对象.
并发执行
现在是多核的时代,为了发挥多核的优势,在有些时候并发执行就非常具有优势。如果在枚举中有许多事要做,但并不关心枚举顺序的情况下,使用并发就很合适。
但是对于数组总量小一些的数组,并发执行不一定会带来性能提升,反而开销可能远多于其带来的好处。
所以具体的使用需要自己进行权衡。
1. 基本的并发枚举块
1
2
3
4
5
6
7
8
9
| - (void) test:(NSArray*)array
{
[array enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(NSString* obj, NSUInteger idx, BOOL *stop) {
NSLog(@"%@",obj);
}];
NSLog(@"end");
}
|
这种方式会为每一个枚举创建一个线程,等到所有的枚举都执行完毕才会进行下一步。
2. 异步GCD并发
1
2
3
4
5
6
7
8
9
10
11
12
| - (void) test:(NSArray*)array
{
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
for(NSString* test in array)
{
dispatch_async(queue, ^{
NSLog(@"%@",test);
});
}
NSLog(@"end");
}
|
这种方式会为每一个枚举创建一个线程,但是不会等待所有枚举执行完成,而是for循环完成后就会进行下一步了,是一种异步执行的方式。
3. 等待GCD并发
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| - (void) test:(NSArray*)array
{
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
for(NSString* test in array)
{
dispatch_group_async(group, queue, ^{
NSLog(@"%@",test);
});
}
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
dispatch_release(group);
NSLog(@"end");
}
|
这种方式使用group将多个block组成一组以监测这些Block全部完成或者等待全部完成。这种方式的效果类似于1.基本的并发枚举块
。
4. dispatch_apply
1
2
3
4
5
6
7
8
9
10
| - (void) test:(NSArray*)array
{
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply(array.count, queue, ^(size_t index){
NSLog(@"%@",array[index]);
});
NSLog(@"end");
}
|
这是系统提供的一种并发执行方式,这种方式的效果同样类似于1.基本的并发枚举块
。
参考
本文只是粗略的介绍,如果想了解更详细的使用,建议阅读下面的链接。
http://www.oschina.net/translate/high-performance-collection-looping-objective-c
http://www.dreamingwish.com/dream-2012/gcd%E4%BB%8B%E7%BB%8D%EF%BC%88%E4%BA%8C%EF%BC%89-%E5%A4%9A%E6%A0%B8%E5%BF%83%E7%9A%84%E6%80%A7%E8%83%BD.html