Obj-C: (loop) 优雅的for...in loop

来源:互联网 发布:vb按钮事件断点 编辑:程序博客网 时间:2024/06/06 09:13

Obj-C: (loop) 优雅的for...in loop

早期的Objective-C, 遍历一个容器类(NSArray, NSSet, NSDictionary)的方式是这样的:

1
2
3
4
5
6
7
8
NSSet*items = [NSSetsetWithObjects:@"foo",@"bar",nil];
                         
NSEnumerator*enumerator = [items objectEnumerator];
NSString*item =nil;      
while(item = [enumerator nextObject])
{
    NSLog(@"%@", item);
}

 

如果是一个有序容器, 比如NSArray, 还可以使用C-style for loop:

1
2
3
4
5
6
7
NSArray*items =[NSArrayarrayWithObjects:@"foo",@"bar",nil];
                        
for(NSUIntegeri = 0; i < items.count; i++)
{
    NSString*item =[items objectAtIndex:i];
    NSLog(@"%@", item);
}

可如果是NSSet这种无序容器, 就只能使用前一种了

 

------------------------------------------ 2.0时代的分割线 ------------------------------------------

 

Objective-C 2.0引入了for...in loop, 极大简化了遍历操作,

用for...in loop遍历一个NSArray:

1
2
3
4
5
6
NSSet*items = [NSSetsetWithObjects:@"foo",@"bar",nil];
                                                                          
for(NSString*item in items)
{
    NSLog(@"%@", item);
}

甚至可以简化成:

1
2
3
4
for(NSString*item in [NSSetsetWithObjects:@"foo",@"bar",nil])
{
    NSLog(@"%@", item);
}

 

当用for...in loop来遍历NSDictionary时, 每次返回的是一个key:

1
2
3
4
5
6
7
8
9
NSDictionary*numbers =[NSDictionarydictionaryWithObjectsAndKeys:
                        @"zero",@"0",
                        @"one",@"1",nil];
                        
for(NSString*key in numbers)
{
    NSString*value =[numbers objectForKey:key];
    NSLog(@"key:%@ value:%@", key, value);
}

 

在遍历一个容器类的同时, 是不能删除, 增加其中的元素的,

1
2
3
4
5
6
7
8
9
NSMutableSet*items =[NSMutableSetsetWithObjects:@"",@"a",@"aa",@"aaa",nil];
                        
for(NSString*item in items)
{
    if(item.length <2)
    {
        [items removeObject:item]; // WRONG!
    }
}

for...in loop引入了 Mutation Guard的机制, 运行时抛出异常:

Collection was mutated while being enumerated

但如果我们真的需要遍历时删除怎么办? 解决方案之一是遍历一个容器的拷贝:

1
2
3
4
5
6
7
8
9
NSMutableSet*items =[NSMutableSetsetWithObjects:@"",@"a",@"aa",@"aaa",nil];
                      
for(NSString*item in [[items copy] autorelease])
{
   if(item.length <2)
   {
       [items removeObject:item];// OKAY
   }
}


原创粉丝点击